自定义指令

除了核心功能默认内置的指令,Vue 也允许注册自定义指令。

自定义指令可以定义全局指令,也可以定义局部指令。

使用 directives 选项来自定义指令。

定义全局指令:

<div id="app">
    <p>页面载入时,input 元素自动获取焦点:</p>
    <input v-focus>
</div>
 
<script>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中。
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

定义局部指令:

<div id="app">
  <p>页面载入时,input 元素自动获取焦点:</p>
  <input v-focus>
</div>
 
<script>
// 创建根实例
new Vue({
  el: '#app',
  directives: {
    // 注册一个局部的自定义指令 v-focus
    focus: {
      // 指令的定义
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    }
  }
})
</script>

钩子函数

指令定义函数提供了几个钩子函数(可选):

  • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

  • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

  • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。

  • componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。

  • unbind: 只调用一次, 指令与元素解绑时调用。

钩子函数参数

钩子函数的参数有:

  • el: 指令所绑定的元素,可以用来直接操作 DOM 。
  • binding: 一个对象,包含以下属性:
    • name: 指令名,不包括 v- 前缀。
    • value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2
    • oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"
    • arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"
    • modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }
  • vnode: Vue 编译生成的虚拟节点。
  • oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<div id="app"  v-runoob:hello.a.b="message">
</div>
 
<script>
Vue.directive('runoob', {
  bind: function (el, binding, vnode) {
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})
new Vue({
  el: '#app',
  data: {
    message: 'Vue.js!'
  }
})
</script>

钩子函数执行顺序:

在页面首次加载执行顺序有如下:

beforeCreate                //在实例初始化之后、创建之前执行
created                         //实例创建后执行
beforeMounted             //在挂载开始之前调用
filters      //挂载前加载过滤器
computed                     //计算属性
directives-bind              //只调用一次,在指令第一次绑定到元素时调用
directives-inserted        //被绑定元素插入父节点时调用
activated                       //keek-alive组件被激活时调用,则在keep-alive包裹的嵌套的子组件中触发
mounted     //挂载完成后调用

 

{{}}                                //mustache表达式渲染页面

 

修改页面input时,被自动调用的选项顺序如下:
watch                           //首先先监听到了改变事件
filters     //过滤器没有添加在该input元素上,但是也被调用了
beforeUpdate              //数据更新时调用,发生在虚拟dom打补丁前
directived-update        //指令所在的组件的vNode更新时调用,但可能发生在其子vNode更新前
directives-componentUpdated//指令所在的组件的vNode及其子组件的vNode全部更新后调用
updated                      //组件dom已经更新

 

组件销毁时,执行顺序如下
beforeDestroy            //实例销毁之前调用
directives-unbind       //指令与元素解绑时调用,只调用一次
deactivated                //keep-alive组件停用时调用
destroyed                  //实例销毁之后调用

 

设置指令背景色:

Vue.directive('runoob', function (el, binding) {
  // 设置指令的背景颜色
  el.style.backgroundColor = binding.value.color
})