简介
Vue自带的指令很多,v-for/v-if/v-else/v-else-if/v-model/v-bind/v-on/v-show/v-html/v-text…但是这些指令都是比较偏向于工具化,有些时候在实现具体的业务逻辑的时候,发现不够用,所以Vue也允许注册自定义指令,自定义指令提供一种机制将数据的变化映射为 DOM 行为。
注册自定义指令的方法:
- 用 Vue.directive(id, definition) 方法注册一个全局自定义指令,它接收两个参数指令 ID 与定义对象。
- 用组件的 directives 选项注册一个局部自定义指令。
钩子函数
定义指令对象可以提供几个钩子函数(都是可选的):
- bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作,v-if使其创建的时候也触发。
- inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
- update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。在componentUpdated执行前触发。
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。元素的隐藏和显示的时候触发,比如display变为block |none、元素移动位置、input输入等“肉眼可见的变化时”,在update执行后触发。
- unbind: 只调用一次, 指令与元素解绑时调用,比如v-if使元素删除的时候。
钩子函数执行简图:
钩子函数的参数有:
- el: 指令所绑定的元素,可以用来直接操作 DOM, 可以利用 $(el) 无缝连接 jQuery。
- 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 钩子中可用。
应当将这些属性视为只读的,不要修改它们。可以给指令对象添加自定义属性,但是注意不要覆盖已有的内部属性。
全局自定义指令
形如:
Vue.directive('指令名(驼峰命名)', {
bind: function () {},
inserted: function () {},
update: function () {}
});
官方指定的指令简写模式(只在bind或update会触发):
Vue.directive('指令名(驼峰命名)', function (el, binding) {
...
});
html使用“v-”形式:
<div id="app" v-指令名="message"></div>
演示:
<body>
<div id="content">
<input v-my-is-show v-if="isVisable" type="text" />
<button v-on:click="isVisable=!isVisable">点击显示/隐藏</button>
</div>
</body>
<script>
Vue.directive("myIsShow", {
bind: function(el) {
console.log("directive---myIsShow---bind");
},
update: function(el) {
console.log("directive---myIsShow---update");
},
inserted: function(el) {
console.log("directive---myIsShow---inserted");
},
unbind: function(el) {
console.log("directive---myIsShow---unbind");
},
componentUpdated: function(el) {
console.log("directive---myIsShow---componentUpdated");
}
});
var vm = new Vue({
el: "#content",
data: {
isVisable: true,
}
});
</script>
加载好页面打印:
directive—myIsShow—bind
directive—myIsShow—inserted
点击按钮input被删除打印:
directive—myIsShow—unbind
再次点击按钮添加input打印:
directive—myIsShow—bind
directive—myIsShow—inserted
但是在input输入框不管怎么输入,都不会打印update,componentUpdated,直到绑定v-model:
//h5
<input v-my-is-show v-if="isVisable" type="text" v-model="txt"/>
//vue
data: {
isVisable: true,
txt:"111"
}
每输入一个字符,打印一段:
directive—myIsShow—update
directive—myIsShow—componentUpdated
看来必须和vue关联起来数据才能触发这两个方法。
局部自定义指令与钩子函数参数
形如:
new Vue({
el: '#app',
directives: {
指令名: {
inserted: function (el) {}
...
}
}
})
演示:
<body>
<div id="content">
<!-- value111的地方也能传递对象{color: 'white', text: 'hello!'} -->
<p v-hello:arg111.modi1.modi2="value111">1+1</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#content',
data: {
value111: "111"
},
directives: {
hello: {
inserted: function(el, binding, vnode) {
var myStr = JSON.stringify;
// console.log("el--->" + $(el).text()); //可以使用jquery引用el
console.log("el--->" + el.innerHTML);
console.log("binding.name--->" + myStr(binding.name));
console.log("binding.value--->" + myStr(binding.value));
console.log("binding.expression--->" + myStr(binding.expression));
console.log("binding.arg--->" + myStr(binding.arg));
console.log("binding.modifiers--->" + myStr(binding.modifiers));
}
}
}
});
</script>
运行:
el—>1+1
binding.name—>“hello”
binding.value—>“111”
binding.expression—>“value111”
binding.arg—>“arg111”
binding.modifiers—>{“modi1”:true,“modi2”:true}