自定义指令
除了默认设置的核心指令(如:v-model,v-for),Vue.js也允许注册自定义指令,自定义指令提供一种机制将数据的变化映射为DOM行为
Vue.js用 Vue.directive(id, definition)方法注册一个全局自定义指令,它接收两个参数:指令ID和定义对象。也可以用组建的directives选项注册一个局部自定义指令
例如:聚焦一个 input 元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<
div
id
=
"directive-focus"
>
<
input
v-focus>
</
div
>
<
script
src
=
"//cdn.bootcss.com/vue/2.0.7/vue.js"
></
script
>
<
script
>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus',{
//将绑定元素插入到 DOM 中
inserted:function(el){
// 聚焦元素
el.focus();
}
})
new Vue({
el:'#directive-focus'
})
</
script
>
|
当页面加载时,元素将获得焦点。事实上,你访问后还没点击任何内容,input 就获得了焦点。
也可以注册局部指令,组件中接受一个 directives 的选项:
1
2
3
4
5
|
directives: {
focus: {
// 指令的定义---
}
}
|
钩子函数
Vue.js提供了几个钩子函数(都是可选的,相互之间没有制约关系):
bind -- 只调用一次,指令第一次绑定到元素上时使用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作
inserted -- 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在document中)
update -- 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新
componentUpdated -- 被绑定元素所在的模板完成一次更新周期时调用
unbind -- 只调用一次,指令与元素解绑时调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Vue.directive(
'my-directive'
,{
bind:
function
(){
//准备工作
//例如,添加事件处理器或只需要运行一次的高耗任务
},
update:
function
(newValue, oldValue){
//值更新时的工作
//也会以初始值为参数调用一次
},
unbind:
function
(){
//清理工作
//例如,删除bind()添加的事件监听器
}
})
|
在注册之后,便可以在Vue.js模板中这样用(记着添加前缀 v-):
1
|
<
div
v-my-directive
=
"someValue"
></
div
>
|
当只需要update函数时,可以传入一个函数替代定义对象:
1
2
3
|
Vue.directive(
'my-directive'
,
function
(value){
//这个函数用作update()
})
|
钩子函数参数
所有的钩子函数都将被复制到实际的指令对象中,在钩子内,this指向这个指令对象。
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 }
descriptor -- 一个对象,包含指令的解析结果
vnode -- Vue编译生成的虚拟节点
oldVnode -- 上一个虚拟节点,仅在update和componentUpdated钩子中可用
vm -- 拥有该指令的上下文ViewModel
除了 el 之外,其它参数都应该是只读的,尽量不要修改他们。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
一个使用了这些参数的自定义钩子样例:
HTML:
1
|
<
div
id
=
"hook-argument-example"
v-demo:hello.a.b
=
"message"
></
div
>
|
JS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Vue.directive(
'demo'
,{
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.argument)+
'<br>'
+
'modifiers:'
+s(binding.modifiers)+
'<br>'
+
'vnode keys:'
+Object.keys(vnode).join(
','
)
}
})
new
Vue({
el:
'#hook-argument-example'
,
data:{
message:
'hello'
}
})
|
页面效果截图:
函数简写
大多数情况下,我们可能想在 bind 和 update 钩子上做重复动作,并且不想关心其它的钩子函数。可以这样写:
1
2
3
|
Vue.directive(
'color-swatch'
,
function
(el, binding) {
el.style.backgroundColor = binding.value
})
|
对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法类型的 Javascript 表达式。
1
2
3
4
5
6
7
8
9
10
11
12
|
<
div
id
=
"demo"
v-demo
=
"{color:'red', text:'hello!'}"
></
div
>
<
script
src
=
"//cdn.bootcss.com/vue/2.0.7/vue.js"
></
script
>
<
script
>
Vue.directive('demo',function(el,binding){
console.log(binding.value.color);
console.log(binding.value.text);
})
var demo = new Vue({
el:'#demo'
})
</
script
>
|
本文转自 frwupeng517 51CTO博客,原文链接:http://blog.51cto.com/dapengtalk/1874582