自定义指令 directive

Vue 中所有的指令,在调用的时候,都以 v- 开头。除了内置的指令( 如 v-if ),Vue 也允许注册自定义指令。

在 Vue2.0 中,代码复用和抽象的主要形式是组件,

然而,有些情况下,仍然需要对普通 DOM 元素进行底层操作,这时,就会用到自定义指令。


语法规则

定义一个自定义指令,主要有两种方式:全局注册( 如,按钮级权限 )和局部注册。其结构如下:

  • 指令名称:顾名思义,“指令的名称”,可自主命名。

在定义的时候,指令名称的前面不需要加 v- 前缀;而,在调用的时候,必须在指令名称前加上 v- 进行调用。

  • 自定义对象:该对象身上,有一些指令相关的钩子函数,这些函数可以在特定的阶段,执行相关的操作
    • 钩子函数 & 参数
      • 动态指令参数

<template>
  <div class="content">
    <input type="text" v-focus v-bgColor="{ bgCol }" />
  </div>
</template>

<script>
import Vue from "vue";
// 定义方式1:全局注册
Vue.directive("focus", {
  // 指令名称 & 自定义指令对象
  inserted: function (el) {
    // 钩子函数 & 参数
    el.focus(); // 获取元素焦点
  },
});
export default {
  data() {
    return {
      bgCol: "red",
    };
  },
  // 定义方式 2:局部注册(使用directives选项)
  directives: {
    // 指令名称
    bgColor: {
      // 自定义指令对象
      inserted: function (el, binding) {
        // 钩子函数 & 参数
        el.style.backgroundColor = binding.value.bgCol; // 改变元素的背景色
      },
    },
  },
};
</script>

理解:钩子函数和参数

一个自定义指令对象,可以提供如下钩子函数( 均为可选 ):

  • bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置
  • inserted:被绑定元素插入父节点时调用( 仅保证父节点存在,但不一定已被插入到文档中 )
  • update:所有组件的 VNode 更新时调用,但可能发生在其子 VNode 更新之前。指令的值,可能发生了变化,也可能没有。可以结合相关参数比较更新前后的值来忽略不必要的模板更新
  • componentUpdated:指令所在的组件的 VNode 及其子 VNode 全部更新后调用
  • unbind:只调用一次,指令与元素解绑时调用
Vue.directive("focus", {
  bind: function (el) {
    // 元素刚绑定指令的时候,还没有插入到DOM中去,这个时候调用focus方法无效,因为一个元素只有插入DOM后才能获取焦点
    // el.focus();         // 时机不对
  },
  inserted: function (el) {
    // 表示元素插入到DOM中的时候,会执行inserted函数(触发一次)
    el.focus();
  },
  updated: function () {
    // 当VNode更新的时候,会执行updated,可能会触发多次
  }
});

钩子函数,可以传入以下参数( 需说明的是,除 el 外,其他参数都应该是只读的,切勿修改 ):

  • el:指令所绑定的元素,可以用来直接操作 DOM,是指令钩子函数的第一个参数。
  • binding:第二个参数,是一个对象。主要包括以下属性:
    • name:指令名称( 不包括 v- 前缀 )如,binding.name,结果为 'bgColor'
    • value:指令绑定的值。如,binding.value.bgCol,结果为 'red'
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 中可用
    • expression:字符串形式的指令表达式,如 v-my-directive="1+1",binding.value.express,结果为 '1+1'
    • arg:传给指令的参数,可选。如 v-my-directive:foo 中,参数为 'foo'
    • modifers:一个包含修饰符的对象。如 v-my-directive.foo.bar 中,修饰符为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点( 移步 VNode API,了解更多 )
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用