《directives》

184 阅读3分钟

目标:自己造出一个 v-x 指令,点击打印出 'x'

一. 声明一个全局指令

全局的意思是,这个指令在任何组件里都能使用

Vue.directive('x',{
  inserted: function (el) {
    el.addEventListener('click',()=>{
      console.log('x')
    })
  }
})

比如定义在main.js里,实例引用了其他组件,那么其他组件里都可以使用 v-x 指令。

v-x 被加到哪个元素上,哪个元素就是el。 inserted 表示元素被插入到DOM中后,给el添加一个点击事件。

二. 声明一个局部指令

new Vue({
    ...,
    directives:{
        'x':{
            inserted: function(el) {
                el.addEventListener("click", () => {
                    console.log("x");
                });
            }
        },
        'y':directiveOptions
    }
})

在一个实例或组件的选项里声明,使用 directives 选项,可以声明多个指令。

v-x 指令只能在该组件里使用,其他地方用不了,包括它引用的组件。

三. directiveOptions

directiveOptions 里有五个函数属性:

  • bind(el,info,vnode,oldVnode):只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。(类似created)

  • inserted(参数同上):被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。(类似mounted)

  • update(参数同上):所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。 (类似updated)

  • componentUpdated(参数同上):指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind(参数同上):只调用一次,指令与元素解绑时调用。(类似destroyed)

前两个和最后一个比较常用。

函数的四个参数:

  • el :指令所绑定的元素,可以用来直接操作 DOM。
  • info :一个对象,包含以下 property:
    • 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 编译生成的虚拟节点。
  • oldVnode :上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

自己实现v-on

new Vue({
  directives: {
    on2: {
      // bind 可以改为 inserted
      bind(el, info) {
        console.log(info)
        el.addEventListener(info.arg, info.value);
        // Vue 自带的 v-on 并不是这样实现的,它更复杂,用了事件委托
      },
      unbind(el, info) {
        el.removeEventListener(info.arg, info.value);
      }
    }
  },
  template: `
    <button v-on2:click="hi">点我</button>
  `,
  methods: {
    hi() {
      console.log("hi");
    }
  }
}).$mount("#app");

声明一个局部指令,on2。当指令绑到元素上时,给元素添加一个事件监听。事件名现在还不知道,需要用户传,比如是一个click事件,可以通过 info.arg 获取。事件处理函数通过 info.value 获取。

好的习惯是给元素绑定事件监听后,要在一个时间解除绑定。于是在元素消亡时解除事件监听。

四. 指令的作用:减少重复的DOM操作

Vue 实例/组件主要用于数据绑定,事件监听,DOM更新

而原生的DOM操作就可以封装成Vue指令

如果某种DOM操作经常使用,或者比较复杂,就可以封装成指令