3x1 精读Vue官方文档 - 自定义指令

869 阅读3分钟

精读 Vue 官方文档系列 🎉

简介

Vue 指令可以分为”内置指令(例如:v-once,v-cloak等)“与“自定义指令“。 Vue 指令提供了操作底层 DOM 的能力,增强了 Vue 模板的处理功能。

  • 局部注册指令,可以使用组件选项 directives
  • 全局注册指令,需要调用 Vue 构造函数的 Vue.directive() 方法

钩子函数

“指令”的构成与组件选项类似,有着自己独特的钩子函数。

  • bind: 只调用一次,当指令与元素进行绑定时调用,此时可以对元素进行初始化操作(比如事件的绑定)。
  • inserted: 被绑定元素插入父节点时调用(但不能保证父节点本身已经插入到文档中)。
  • update: 组件更新之前调用。
  • componentUpdated: 组件更新之后调用。
  • unbind: 只调用一次,当指令与元素解绑时调用,例如 v-if 控制的组件。

bindinserted 区别

bindinserted
是在元素(Vdom)被创建后并与指令进行绑定时调用。元素与指令绑定完成,并被插入到父节点时调用。
触发时元素没有插入到父节点中,所以 el.parentNode 返回为 null调用在 bind 之后,此时元素已经插入到父节点中,所以 el.parentNode 可以正确返回父节点的引用。
是在 DOM 树绘制之前调用,因而获取不到有关元素渲染的信息。函数是在 DOM 树绘制之后调用,因而可以获取到有关元素渲染的信息。
Vue.directive('dom',{
  bind(el){
    console.log(el.offsetWidth); //0
    console.log(el.parentNode);  //null
  },
  inserted(el){
    console.log(el.offsetWidth); //1170
    console.log(el.parentNode);  //<div msg="Welcome to Your Vue.js App"><button>click</button><div>false</div></div>
  }
})

updatecomponentUpdated 差异

它们的区别更像是 beforeUpdateupdated

<button @click="show = !show">click</button>
<div v-dom>{{ show }}</div>

此时,点击按钮切换响应式数据 show 的值为 true,观察自定义指令的输出:

Vue.directive("dom", {
  update(el) {
    console.log("update", el.innerHTML); //'update false'
  },
  componentUpdated(el) {
    console.log("componentUpdated", el.innerHTML); //'componentUpdated true'
  },
});

自定义指令钩子中没有 Vue 实例,this 默认指向 undefined

钩子函数参数

完整的指令结构:

<span v-directiveName:argument.modifier="show"></span>

是否很抽象,那么代入实际例子去理解:

<button v-on:mousemove.passive="doSomeThing"></button>

Vue 指令的钩子方法会接收以下四个参数:

  1. el : 当前指令所绑定的元素。
  2. binding : 指令本身的信息,值为一个对象。
    • name : 指令的名称。
    • rawName : 完整原始名称,含 v-* 前缀。
    • value: 指令的值。
    • expression : 指令的表达式。
    • arg : 传给指令的参数,支持动态参数。
    • modifiers : 指令的修饰符。
    • oldValue : 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  3. vnode : Vue 编译生成的虚拟节点。
  4. oldVnode : 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

valueexpression 的联系

Vue 指令被调用时可以接收一个符合 JavaScript 规定的字符串形式的“表达式”的值(核心就是指令的值)。而 value 则是 expression 执行最终计算后的值。

v-calc="1 + 1"
//expression "1+1"
//value 2;

常见的表达式,例如原始表达式、算术表达式、对象和数组的初始化表达式、调用表达式等。

expressionvalue
"true"true
"1"1
"'hello'""hello"
"show"(响应式变量)false
"{x: 2.3, y: -1.2}"{x: 2.3, y: -1.2}
"1 + 2"3
"(v)=>{}"ƒ (v)

动态指令参数

指令的参数可以是动态的。例如,在 v-dom:[argument]="value" 中,argument 参数可以根据组件实例的响应式数据进行更新,这使得自定义指令可以在应用中被灵活使用。

Vue.directive("dom", {
  bind(el, binding) {
    if (binding.arg === "color") {
      el.style.color = binding.value;
    } else if (binding.arg === "background") {
      el.style.background = binding.value;
    }
  },
});

使用指令的方式:

<div v-dom:background="'red'">{{ show }}</div>
<div v-dom:color="'green'">{{ show }}</div>

返回已注册的指令

Vue.directive('directiveName');