在Vue2.0中代码复用和抽象的主要形式是组件,但对普通DOM元素进行底层操作,我们还是要用到自定义指令。
<div id="app">
<h3>自定义指令</h3>
<input type="text" v-sun="message" />
</div>
<script type="text/javascript">
$(document).ready(function(){
// 自定义指令的各个钩子的区别
Vue.directive('sun',{
bind:function(el,binding){
// 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作
el.value='bind:'+binding.value;
console.log(el.value);
},
inserted:function(el,binding){
// 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)
el.value='inserted:'+binding.value;
console.log(el.value);
},
update:function(el,binding){
console.log('update:'+el.value);
},
componentUpdated:function(el,binding){
// 被绑定元素所在模板完成一次更新周期时调用
console.log('componentUpdated:'+el.value);
},
unbind:function(el,binding){
// 只调用一次,指令与元素解绑时调用
console.log('unbind:'+el.value);
}
});
new Vue({
el:'#app',
data:{
message:'hello!',
}
});
});
</script>
一个指令定义对象可以提供如下几个钩子函数(均为可选):
- bind:只调用一次,指令第一次绑定到元素时调用。在这里进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。
- componentUpdate:指令所在组件的VNode及其子VNode全部更新后调用。
- unbind:只调用一次,之领域元素解绑时调用。
钩子函数的参数:
<div id='app'>
<div v-demo='message'></div>
</div>
<script type='text/javascript'>
$(document).ready(function(){
Vue.directive('demo',{
bind:function(el,binding,vnode){
let 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:'hello'
}
});
});
</script>
- el:指定所绑定的元素,可以直接操作DOM。
- binding:一个对象,包含若干属性。
- vnode:Vue编译生成的虚拟节点。
- oldVnode:上一个虚拟节点,尽在update和componentUpdated钩子函数中可用。
binding对象包含的属性:
- name:指令名,不包含v-前缀
- value:指令的绑定值,例如:v-mode='1+1'中,绑定值为2。
- oldValue:指定绑定的前一个值,仅在update和componentUpdate钩子中可用,无论是否改变都可用。
- expression:字符串形式的指令表达式,例如:v-mode='1+1'中,表达式为'1+1'。
- arg:传给指令的参数、可选。例如v-demo:foo中,参数为'foo'。
- modifiers:一个包含修饰符的对象。例如:v-demo.foo.bar中,修饰符对象为{foo:true,bar:true}。
函数简写:
在bind和update时触发相同的行为,而不关心其他的钩子,有如下写法:
<script type='text/javascript'>
$(document).ready(function(){
Vue.directive('demo',function(el,binding){
el.style.backgroundColor = binding.value
});
});
</script>
对象字面量:
如果指令需要多个值,可以传入一个JavaScript对象字面量,指令函数能够接受所有合法的JavaScript表达式
<div v-demo="{color:'white',text:'hello!'}"></div>
<script type='text/javascript'>
$(document).ready(function(){
Vue.directive('demo',function(el,binding){
console.log(binding.value.color); // 'white'
console.log(binding.value.text); // 'hello!'
});
});
</script>