我的VUE 学习之路(下)

Posted 众纳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的VUE 学习之路(下)相关的知识,希望对你有一定的参考价值。

前言:

        在经历过前面在html下的VUE相关基础的洗礼后,我们可以动手去做一些事了,此时发现直接通过直接VUE组件方式与之前在HTML不同,首先要“静一静”,细看之下只是对之前的很多写法做了封装。

        本文旨在直接上手Vue项目下做测试而非前面的那种方式。

预期目标:VUE项目开发的基本理解

使用工具:HBuilder

学习前技术储备:VUE 在HTML下的使用

零、准备

下载与配置Vue CLI

注意事项:

创建项目时如果提示:无法加载文件 vue.ps1.......

解决方案:

1.以管理员身份打开windows PowerShell 

2.输入:set-ExecutionPolicy RemoteSigned 

3.选择y或者a

4.回车 就可以了

一、Vue 项目走步

1.1.项目创建

 1.在对应的目录上支行CMD或终端

2.输入 vue create XXX                                        [xxx 是项目名称]

3.选择配置(如下图)通常情况下需要手动配置

 4.手动配置 选项说明

        4.1Babel (默认选中)(选中)

        4.2 TypeScript  --TS库 

        4.3 Progressive Web App...

        4.4 Router        --路由组件(建议选中)

        4.5 Vuex           --状态组件(建议选中)

        4.6 CSS Pre-processors  --样式管理(建议选中)

        4.7 Linter / Formatter(默认选中)(个人不推荐 稍有错误就会提示错误,影响开发速度)

        4.8 Unit Testing  --测试

        4.9 E2E Testing  --测试

5.创建就慢慢等

6.创建后可以使用WebStrom 、VScode 、Hbuilder以项目的打开(导入)就可以了

1.2.项目结构

1.3.项目文件

 系统处理顺序个人理解是:public/index.html  -> main.js->App.vue(如果不对请留言指正)

1.4.项目示例

HomeView.vue 文件调用模组Demo.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
<!--    <HelloWorld msg="Welcome to Your Vue.js App"/>-->
    <demo></demo>
  </div>
</template>

<script>
// @ is an alias to /src
// import HelloWorld from '@/components/HelloWorld.vue'
import Demo from '@/components/Demo'

export default 
  name: 'HomeView',
  components: 
    // HelloWorld,
    Demo
  

</script>
<template>
  <div>
    msg
    <input type="text" ref="mytest">
    <button @click="test()">测试</button>
    <ul>
      <li v-for="data in inputData" :key="data">data</li>
    </ul>
  </div>
</template>
<script>
// 接口
export default 
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'Demo',
  // 数据层
  data () 
    return 
      msg: '这是一个Demo',
      inputData: []
    
  ,
  // 事件
  methods: 
    test () 
      // eslint-disable-next-line no-sequences,no-unused-expressions
      console.log(this.$refs.mytest.value),
      this.inputData.push(this.$refs.mytest.value)
    
  

</script>

二、反向代理概念

它存在的意义在于解决跨域问题,主要是通过修改vue.config.js 处理。

(ps:修改后要重新启动一下才生效

const  defineConfig  = require('@vue/cli-service')
// 示例解决 http://t.163.move/getMove/getById?10
module.exports = defineConfig(
  transpileDependencies: true,
  devServer: 
    proxy: 
      '/getMove':  // API标识
        target: 'http://t.163.move', // 代理标识
        // wss: true,
        changeOrigin: true
      
    
  
)

// 调用 axios.get("/getMove/getById?10").then(res=>res.data)

三、路由

        路由顾名思意就是负责转发或跳转的,与我们生活中的路由器的工作方式相同;在下载的文件中包含了一个示例(router\\index.js),所有接受路由的地方需要用<router-view></router-view>容器接收。

 一级路由

        其实VUE在创建时就给示出一个一级路由实例;

        App.vue

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
    </nav>
    <router-view/>
  </div>
</template>

<style lang="scss">
#app 
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;


nav 
  padding: 30px;

  a 
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active 
      color: #42b983;
    
  

</style>

       router\\index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'


Vue.use(VueRouter)

const routes = [
  
    path: '/',//访问路径
    name: 'home',//命名
    component: HomeView //外部注册 这里直接使用
  ,
  
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')//内部引用
  
]

const router = new VueRouter(
  mode: 'history',//路由模式  展示方式
  base: process.env.BASE_URL,
  routes
)

export default router

        

 多级路由

作用:用于访问子路径  通常使用在二级目录配置

Demo.vue 模拟父(注意定义对应接收标签)

<template>
  <div>
    这是一个Demo 为的是展示二级(多级)路由
    <!--    设置好容器-->
    <router-view></router-view>
  </div>
</template>

定义两个子组件 A.vue  与B.vue

<template>
  <div> A </div>
</template>
<template>
  <div>B</div>
</template>

配置路由新增


  
    path: '/demo',
    name: 'demo',
    component: Demo,
    children:[
        
          path:'a',
          name:'a',
          component:A
        ,
      
        path:'b',
        name:'b',
        component:B
      
    ]
  

动态路由

用途:主要用于路径是变化,但格式固定,通常使用在列表中的详情页

ProductDetail.vue 模拟产品详情

<template>
  <div>
    这是一个组件
    <div> id</div>
  </div>
</template>
<script>
export default 
  data()
    return
      id:""
    
  ,
  mounted()
    this.id=this.$route.params.id
  

</script>

AboutView.vue 模拟数据(产品)列表页,用于发出明细请求

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <ul>
      <li v-for="data in list" :key="data.id" @click="theProduct(data.id)">
        data
      </li>
    </ul>
  </div>
</template>
<script>
export default 
  data()
    return
      list:[id:1,code:"aa",id:2,code:"bb",id:3,code:"cc"]
    
  ,
  methods:
    theProduct(id)
      this.$router.push(`/detail/$id`)//指向router这个目录下的配置实现跳转  动态路由方式1
      //this.$router.push(name:"detail",params:id:id)//动态路由方式2 通过命名路由方式跳转
    
  

</script>

路由配置

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import ProductDetail from '../components/ProductDetail'

Vue.use(VueRouter)

const routes = [
  
    path: '/',//访问路径
    name: 'home',//命名
    component: HomeView //外部注册 这里直接使用
  ,
  
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')//内部引用
  ,
  
    path:'/detail/:id',
    name:'detail',
    component: ProductDetail
  
  
]

const router = new VueRouter(
  mode: 'history',//路由模式  展示方式
  base: process.env.BASE_URL,
  routes
)


export default router

 路由拦截

作用:路由前的校验,一般用于登陆等

如下代码在路由js中添加进去代表当不是demo路径的访问就放行

//路由拦截配置
 router.beforeEach((to,from,next) =>
   if (to.name !=='demo')
     next()
   
 )

路由定向

作用:当访问未在路由内部配置的路径时要自动指向指定的路径

如下配置当访问 .../demo/c的时候自动转向.../demo这个路径上


    path: '/demo',
    name: 'demo',
    component: Demo,
    children:[
        
          path:'a',
          name:'a',
          component:A
        ,
      
        path:'b',
        name:'b',
        component:B
      ,
      
        //重定向
        path: '*',
        redirect:'/demo'
      
    ]
  

全部示例代码

components\\productDetail.vue

<template>
  <div>
    这是一个组件
    <div> id</div>
  </div>
</template>
<script>
export default 
  data()
    return
      id:""
    
  ,
  mounted()
    this.id=this.$route.params.id
  

</script>

router\\index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import ProductDetail from '../components/ProductDetail'
import Demo from '../views/Demo'
import A from '../views/Demo/A'
import B from '../views/Demo/B'

Vue.use(VueRouter)

const routes = [
  
    path: '/',//访问路径
    name: 'home',//命名
    component: HomeView //外部注册 这里直接使用
  ,
  
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')//内部引用
  ,
  
    path:'/detail/:id',
    name:'detail',
    component: ProductDetail
  ,
  
    path: '/demo',
    name: 'demo',
    component: Demo,
    children:[
        
          path:'a',
          name:'a',
          component:A
        ,
      
        path:'b',
        name:'b',
        component:B
      ,
      
        //重定向
        path: '*',
        redirect:'/demo'
      
    ]
  ,
    //重定向:在顶级目录中不存在的数据自动指向首页
  
    path: '*',
    redirect:'/'
  
]

const router = new VueRouter(
  mode: 'history',//路由模式  展示方式
  base: process.env.BASE_URL,
  routes
)
//路由拦截配置
// router.beforeEach((to,from,next) =>
//   if (to.name !=='demo')
//     next()
//   
// )

export default router

views\\AboutView.vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <ul>
      <li v-for="data in list" :key="data.id" @click="theProduct(data.id)">
        data
      </li>
    </ul>
  </div>
</template>
<script>
export default 
  data()
    return
      list:[id:1,code:"aa",id:2,code:"bb",id:3,code:"cc"]
    
  ,
  methods:
    theProduct(id)
      this.$router.push(`/detail/$id`)//指向router这个目录下的配置实现跳转  动态路由方式1
      //this.$router.push(name:"detail",params:id:id)//动态路由方式2 通过命名路由方式跳转
    
  

</script>

views\\Demo.vue

<template>
  <div>
    这是一个Demo 为的是展示二级(多级)路由
    <!--    设置好容器-->
    <router-view></router-view>
  </div>
</template>

views\\Demo\\A.vue

<template>
  <div> A </div>
</template>

views\\Demo\\B.vue

<template>
  <div>B</div>
</template>

App.vue

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/detail">detail</router-link>
    </nav>
    <router-view/>
  </div>
</template>

<style lang="scss">
#app 
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;


nav 
  padding: 30px;

  a 
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active 
      color: #42b983;
    
  

</style>

四、Vuex

vuex 是Vue家族中的状态管理工具。PC端常用于权限管理,移动端则多数用于懒加载。其配置文件前文已介绍就是store目录下的index.js文件。请大家看我针对这个文件的注释

import Vue from 'vue'//引用vue
import Vuex from 'vuex'//引用状态管理
import axios from 'axios'

Vue.use(Vuex) //加载


//导出
export default new Vuex.Store(
  state: 
    //---------------作用:共享数据    第三个加载
    productList:[]
  ,
  getters: 
    //---------------作用:数据二次加工方法
    getProductListTop3(state)
      return state.productList.filter((item,index)=>index<4)
    
  ,
  mutations: 
    //---------------作用:配置系统常量比如登陆的账户信息、权限信息等  第二个加载
    setProductList(state,data)
      state.productList=data
    
  ,
  actions: 
    //---------------作用:异步加载 条件执行,常用于懒加载  第一个加载
    getProductList(store)
      axios(
        url:"http://127.0.0.1:2022/company-work-time/findByCompanyId?companyId=74"
      ).then(res=>
        //state.productList=res.data;
        store.commit("setProductList",res.data.data)
        console.log(res.data.data)
      )
    
  ,
  modules: 
    //---------------状态树,暂时用不到,一般较大项目使用,相当于声明一个子对象一样包含state\\getters...
  
)

1.先加载actions,它主要用于做数据请求。

2.请求过来的数据通过mutations的方法把数据存入state中的变量中去。

3.如果前端需要二次处理,则把方法写在getters中去。

示例

App.vue

<template>
  <div id="app">
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      <router-link to="/storeDemo">storeDemo</router-link>
    </nav>
    <router-view/>
  </div>
</template>

<style lang="scss">
#app 
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;


nav 
  padding: 30px;

  a 
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active 
      color: #42b983;
    
  

</style>

StoreDemo.vue

<template>
  <div>
    <h3>演示状态管理</h3>
    <h5>1:懒加载</h5>
    <ul>
      <li v-for="data in $store.state.productList" :key="data.id">
        data
      </li>
    </ul>
  </div>
</template>
<script>
  export default 
    data()
      return
        pList:[]
      
    ,
    mounted() 
      if (this.$store.state.productList.length===0)
        this.$store.dispatch("getProductList")
      else 
        console.log("启用缓存数据")
        this.pList=this.$store.state.productList
      
    
  
</script>

五、elementUI 、MintUI

其实这方面的教程非常多,而且官方相当详尽,在这里只是给大家提醒有这么一个东西,首先它是界面优化的(可以理解为基于VUE的皮肤),Element 是针对PC端的,Mint是针对移动端的。以下是官方连接方便大家查用

Element UI

Mint UI

总结

个人觉得VUE最大的亮点:

1.组件化开发【像是乐高积木,越细分越灵活】

2.数据双向绑定

结论:

作为一名开发人员不应该抱着固有的思想看问题,一项技术出来并且有生命力指定有它的先进性,我们要主动拥抱它!我遇到很多技术人员总在讲:“XXXX已经足够用了”、“用XXX也能实现这个需求(除了麻烦点)”,更有过者讲:“XXX不好用(其实用都没有用过就发表看法)”............遇到这些人我们尽量远离切不可与之争论,因为这些负能量会影响到你!

文未提醒大家这是我学习近两周后的一些个人心得与技术总结,难免有一些差错,届时希望大家批评指正,同时原创不易,欢迎收藏转发。

vue学习之路 - 4.基本操作(下)

vue学习之路 - 4.基本操作(下)

简述:本章节主要介绍 vue 的一些其他常用指令。

Vue 指令

  这里将 vue 的指令分为系统内部指令(vue 自带指令)和用户自定义指令两种。

系统内部指令

  v-if

  v-else

  v-else-if

  v-for

  v-on

  v-bind

  v-model

  以上指令前面都已说明其作用,并且使用过,这里将不再赘述。

下面我们看看 vue 的一些其他常用指令的用法:

在学习 v-text 和 v-cloak 之前我们先看看{{ }}的使用所存在的问题。 

  {{ }}存在的问题:页面初始化时,可能会出现闪烁问题。当数据量越大的时候,这个问题就更加明显。

  如下面这段代码:

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue- {{ }} 的闪烁问题</title>
</head>
<body>
  <!----------{{ }} 存在的闪烁问题------------------------------>
  <!-- 为什么{{ }}会在页面加载时出现闪烁?
       答:浏览器自上而下一次对页面代码进行解析,当解析到<h1>{{ foo }}</h1>的时候,浏览器会直接把{{ foo }}
           当做h1标签的内容直接渲染出来。
           然后解析到了Vue之后,Vue就要从入口管理模板,解析{{ foo }}变成了foo的值:hello 
           中间这个阶段就会一闪而过。
   -->
  <div id="app">
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        foo : hello
      }
    })

  </script>
</body>
</html>
{{ }}的闪烁问题演示代码

  运行效果:初次加载或者重新加载界面,都有可能会在界面闪一下显示出{{ }}的符号。

  解决{{  }}闪烁问题的方案有两种:

    ①    使用v-text指令,替换{{ }}

    ②    使用v-cloak指令,作用与整个被vue 管理的 div 块。

  详情请看下面 v-text 和 v-cloak 指令介绍。

v-text

  v-text 的使用效果和{{ }}的作用差不多,但是 v-text 不存在闪烁问题。

  v-text使用Demo:

  - 和{{ }}一样的,唯一的区别就是,{{ }}会造成闪烁问题,v-text不会造成闪烁问题

  - 如果还想用{{ }}又不想有闪烁问题,则用v-cloak指令来处理。(详情看v-cloak指令)

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-指令 v-text</title>
</head>
<body>
  <!-- 用v-text解决闪烁问题 -->
  <div id="app">
    <h1 v-text="foo"></h1>
    <h1 v-text="foo"></h1>
    <h1 v-text="foo"></h1>
    <h1 v-text="foo"></h1>
    <h1 v-text="foo"></h1>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        foo : hello
      }
    })

  </script>
</body>
</html>
v-text 示例

v-cloak

  - 如果想用{{  }}进行数据显示,又不想有闪烁问题,则使用v-cloak来处理

    ■ 先在在样式表添加一个特殊样式[v-cloak] { display: none }

    ■ 然后在被vue管理的模板入口节点上作用v-cloak指令。

  - 原理:加上这个display:none的属性后,默认一开始被vue管理的模板时隐藏的,当vue解析处理完DOM模板后,会自动把这个样式去除,然后显示出来

  Demo:

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-指令 v-cloak</title>
</head>
<body>
  <!-- 如果你还是想要使用{{ }}进行数据显示的话,可以使用v-cloak解决闪缩问题 -->
  <!-- 用v-cloak解决闪烁问题 -->
  <!-- 
    原理:默认给div内容是display: none的样式,
         但是当vue加载完成后,会自动将v-cloak去除。
  -->
  <style type="text/css">
    [v-cloak] {
        display: none;
      }
  </style>

  <div id="app" v-cloak>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
    <h1>{{ foo }}</h1>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        foo : hello
      }
    })

  </script>
</body>
</html>
v-cloak 示例

v-html

  把要显示的字符串当做 html 代码来进行渲染。

  Demo:

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-指令 v-text</title>
</head>
<body>
  <div id="app" v-cloak>

    <!-- 普通的文本绑定渲染:结果会当做字符串直接渲染 -->
    <div>{{ htmlStr }}</div>

    <!-- 使用v-html指令的文本渲染,会将这段文本当做HTML代码进行渲染 -->
    <div v-html="htmlStr"></div>

  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        htmlStr : <div>我是一段HTML文本</div>
      }
    })
  </script>
</body>
</html>
v-html 示例

  运行效果:

技术分享图片

  注意:v-html 的文本渲染会对里面的脚本进行过滤,遇到脚本会忽略过去,不执行。

      - Vue在这里做了安全处理,如果发现有script标签,则不渲染

      - 原因:防止XSS攻击。

  XSS攻击:XSS攻击就是利用往网页注入js脚本,读取cookie,发送到黑客服务器中或者直接在你访问的这个网站,当你结算账单的时候,跳转到钓鱼网站

v-show

  根据表达式之真假值,切换元素的 display css 属性。

  作用:条件控制元素的显示或隐藏

    - 无论真假,都会渲染在DOM结构中

      ■ 条件为真,则让display显示

      ■ 条件为假,则让display不显示

  建议:如果需要频繁的显示或隐藏切换,则使用v-show

  v-if 和 v-show的区别:

  v-if:

    - 真正的条件渲染,不满足渲染条件都不会渲染在DOM结构中

    - 条件为真,则渲染这个DOM

    - 条件为假,则移除或不渲染这个DOM

    - 建议:如果只是一次显示和隐藏的控制,则建议使用v-if

v-pre

  跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-指令 v-pre</title>
</head>
<body>
  <!-- v-pre -->
  <div id="app" v-cloak>
      
    <!-- Vue 不处理带有 v-pre 指令的DOM元素
            例如:一个网页的一篇文章,文章内容就不需要被Vue管理渲染。
                 所以我们就可以在文章内容节点上加v-pre来忽略这个DOM处理
                 用以提高性能
     -->
     <!-- 正常的块内容, vue 都会对其编译解析 -->
     <h1>{{ foo }}</h1>

    <!-- v-pre 内为原生的 html 编译 -->
    <div v-pre>
      <h1>{{ foo }}</h1>
    </div>

  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        foo : hello
    }
  });
  </script>
</body>
</html>
v-pre 示例

  使用效果:

  技术分享图片

v-once

  只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

  Demo:

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-指令 v-pre</title>
</head>
<body>
  <div id="app">

     <!-- v-once内的DOM元素只渲染一次,后面就算数据更新了
          v-once内的DOM元素都不会再更新渲染。
      -->
    <div v-once>
      <h1>{{ foo }}</h1>
      <h1>{{ foo }}</h1>
      <h1>{{ foo }}</h1>
    </div>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // 得到 Vue 实例
    const app = new Vue({
      el: #app,
      data: {
        foo : hello
      }
    })
  </script>
</body>
</html>
v-once 示例

   运行效果:

  技术分享图片

自定义指令

  除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

注册绑定方式:

  - 关于指令的名字

    ■ 名字中不要加v-前缀(只有使用的时候才加)

    ■ 如果有多个单词,则建议使用驼峰命名法

    ■ 在使用的时候,首先加v-前缀,然后对于驼峰命名法的指令要转换为小写,用-拼接起来。

全局注册

    ■ Vue.directive(‘指令名称’, { 配置参数 } );

    ■ 如果是全局指令,则一定要在实例化Vue之前注册

    ■ 全局注册在所有组件(实例)中都可以使用

    ■ 建议:如果需要在任何组件中可能使用的指令把其注册成全局指令

  全局注册Demo:

// 注册一个全局自定义指令 `v-focus`
Vue.directive(‘focus‘, {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

局部注册

    ■ 通过组件中的选项directives来注册(组件内容在下一章节将介绍)

    ■ 指令的名字作为directives对象的成员

    ■ 局部自定义指令只能在这个组件(实例)中使用

    ■ 建议:如果只是在某个组件中使用(其他组件不可能用到),这个时候注册为组件局部指令

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

自定义指令的使用:

  像系统指令一样的使用方式操作即可使用。

<input v-focus>

 

指令的生命钩子函数:

  - bind

    ■ 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。而且在这个阶段拿不到父元素。

  - inserted

    ■ 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

    ■ 如果你需要操作作用指令的父元素,则最起码写到这个 inserted 中

  - update

    ■ 指令的绑定的值发生更新的时候才会触发调用,获取的是更新的之前的指令所在的 DOM 内容

  - componentUpdated

    ■ 指令的绑定的值发生更新的时候才会触发调用,获取的是更新之后的最新 DOM 内容

  - unbind

    ■ 只调用一次,指令与元素解绑时调用。

  //  bind 和 inserted 的相同之处是一上来都执行一次,以后再也不会执行

  // 异同之处在于,bind 拿不到父元素,inserted 可以拿到父元素

钩子函数参数

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。具体可以参考 VNode API 解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

  注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

基本操作:

技术分享图片
  <script type="text/javascript">
    
    Vue.directive(focus, {
      // 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
      bind (el) {
        console.log(bind 第一次绑定元素) 
      },
      // 只调用一次,被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
      // 如果需要对父节点进行操作,则代码写在此处
      inserted (el) {
        console.log(inserted, el.parentNode)
      },
      // update 拿到的是数据改变视图之前的视图内容,可以通过比较更新前后的值来忽略不必要的模板更新。
      update () {
        console.log(update)
      },
      // componentUpdated 拿到的是数据改变视图之后的视图内容
      componentUpdated () {
        console.log(componentUpdated)
      },
      // 只调用一次,指令与元素解绑时调用。
      unbind () {
        console.log(unbind)
      }
    })

  </script>
指令的生命钩子Demo

函数简写:

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。

比如这样写:

  - 模拟v-show

  <script type="text/javascript">
    // 很多时候,我们都会在 bind 和 update 中执行相同的代码
    // 所以我们可以使用简写方式,直接给一个函数,该函数会作为 bind 和 update 的时候执行的函数
    Vue.directive(my-show, function (el, binding) {
      if (binding.value) {
        el.style.display = block
      } else {
        el.style.display = none
      }
    })
  </script>

  - 模拟v-bind

  <script type="text/javascript">
    Vue.directive(my-bind, function (el, binding) {
      el.setAttribute(binding.arg, binding.value);
    })
  </script>

 

以上是关于我的VUE 学习之路(下)的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js 入门之路

初识vue.js,我的学习之路

vue

Flask 服务于 Vue.js 包文件。更改时重新编译?

前端快来!最火的 Vue.js 开源项目出炉

VueRouter 未定义