Vue 自定义指令

本文将介绍指令,通过它能够实现对”对元素操作的代码”的复用。

一、什么是指令?

如果需要对元素进行操作,且该操作会重复出现,便可以使用指令。

在 Vue 中,指令一般是 v-指令名 形式。

常用的内置的指令包括:v-htmlv-ifv-forv-onv-modelv-bind 等。

二、什么是自定义指令?

除了使用 Vue 自带的指令之外,还允许自定义指令,具体做法是:

  • 编写:编写指令定义对象
  • 注册:注册指令,并在注册时提供指令名
  • 应用:在希望操作的元素之上添加指令

示例:

自定义指令:

1
2
3
4
5
6
7
export default {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
}

全局注册:

1
2
3
import v-focus from './v-focus'

Vue.directive('focus', v-focus)

应用指令:

1
<input v-focus>

这段代码实现的效果是:

自定义了一个 v-focus 指令,它可以被用在模板元素之上,被应用的模板元素将在其加载时尝试获取焦点。

三、编写

1. 结构

1
2
3
{
···可选的钩子函数···
}

2. 钩子函数

指令定义对象中可以使用以下几个钩子函数,它们均是可选的:

  • bind:只调用一次,指令第一次绑定到元素时调用
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用
  • unbind:只调用一次,指令与元素解绑时调用

3. 钩子函数参数

钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM

  • binding:一个对象,包含以下 property:

    • name:指令名,不包括 v- 前缀

    • value:指令的绑定值

      例如:

      v-my-directive="1 + 1" 中,绑定值为 2

    • oldValue:指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用

    • 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:上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

需要注意的是:除了 el 之外,其它参数都不应修改。

4. 示例

1
2
3
4
5
6
7
8
9
10
11
12
{
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(', ')
}
}

四、注册

1. 全局注册

1
Vue.directive(指令名, 指令定义对象)

2. 局部注册

使用组件中的 directives 选项将自定义指令注册到组件之中。

1
2
3
4
5
6
7
8
<script>
export default {
name: ···,
directives: {
指令名: 指令定义对象
}
}
</script>

五、参数传递

Vue 允许在自定义指令应用时向自定义指令传递参数,从而使得使用更加灵活

1. 绑定值

传递:

1
v-指令名="绑定值"

接收:

1
2
3
4
5
6
7
8
// 获取绑定值的值
binding.value

// 获取绑定值的旧值
binding.oldValue

// 获取绑定值的字符串表达式
binding.expression

2. arg

传递:

1
v-指令名:"arg值"

接收:

1
binding.arg

参考