vue自定义指令
什么是自定义指令:在实际的开发过程中,vue内置指令并不能满足所有的需求,或者说想为元素附件一些特别的功能,这时候,就需要用到 Vue 提供的 自定义指令。
自定义指令的钩子函数:
- bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调 (仅保证父节点存在,但不一定已被插入文档中)。
- update:组件更新时调用。
- componentUpdated:组件 和 子组件 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
钩子函数的参数:
- el:指令所绑定的元素,可以用来直接操作 DOM,el永远是钩子函数的第一个参数。
- binding:是一个对象,可以获取绑定指令时传入的参数,包含以下 属性:
- name:指令名,不包括 v- 前缀。 value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- 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:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
注意: 除了 el 之外,binding和VNode 的属性都是只读的,且除了 update和componentUpdated之外,其他的钩子函数只有el,binding,VNode三个参数。
全局自定义指令:在vue实例化之前定义的自定义指令叫做全局自定义指令,定义之后的任何实例中都可以调用。
语法格式:
Vue.directive('指令名称',{
钩子函数(){}
})
<div id="app">
<!-- 传参的时候,传入的是字符串,所以需要加上引号 -->
<h1 v-border="'red'">全局自定义指令</h1>
<h1 v-border="'green'">全局自定义指令</h1>
</div>
<script>
// 在实例化vue对象之前定义,定义的时候指令名称前面不需要加 v-
Vue.directive('border',{
// inserted:被绑定的元素插入父节点时调用指令
inserted(el,binding,vnode){
// binding.value是自定义指令绑定的值,使用模板字符串解析
el.style.border = `2px solid ${binding.value}`;
}
})
new Vue({
el:'#app',
data:{}
})
</script>
运行结果:
**局部自定义指令:**在vue实例化组件中定义的指令叫做局部自定义指令,只能在该实例中调用。
语法格式:
new Vue({
directives:{
指令名称:{
钩子函数(){}
}
}
})
<div id="app">
<!-- 传参的时候,传入的是字符串,所以需要加上引号 -->
<h1 v-border="'blue'">局部自定义指令</h1>
</div>
<div id="app1">
<h1 v-border="'blue'">局部自定义指令</h1>
</div>
<script>
new Vue({
el:'#app',
data:{},
directives:{
// 指令名称
border:{
inserted(el,binding,vnode){
el.style.border = `2px solid ${binding.value}`
}
}
}
})
new Vue({
el:'#app1',
})
</script>
运行结果:
局部指令定义在 el:’#app’ 的vue实例中,所以在 id=“app” 的div中可以成功的调用,但是在 el:’#app1’ 的vue实例中调用就会报错。
自定义指令模拟v-show的效果demo
v-show:元素的显示与隐藏,基于 css 样式的切换。如果确定要隐藏,会给元素的 style 加上display: none。
<div id="app">
<button @click="isShow = !isShow">按钮</button>
<!-- 传参的时候,传入的是字符串,所以需要加上引号 -->
<h1 v-myshow="isShow">自定义指令模拟v-show的效果demo</h1>
</div>
<script>
// 定义全局指令
Vue.directive('myshow',{
// 元素插入父节点时调用组件,isShow初始值是true,页面默认直接显示
inserted(el,binding,vnode){
let dis = binding.value?'block':'none';
el.style.display = dis;
},
// 点击按钮之后,组件中的数据更新发生变化,重新调用组件
update(el,binding,vnode) {
let dis = binding.value?'block':'none';
el.style.display = dis;
},
})
new Vue({
el:'#app',
data:{
isShow:true
},
})
</script>
运行结果:
总结:
- bind():当指令绑定在 HTML 元素上时触发
- inserted():当指令绑定的元素插入到父节点中的时候触发
- update():当指令绑定的元素状态/样式、内容(这里指元素绑定的 vue 数据) 发生改变时触发
- componentUpdated():当 update() 执行完毕之后触发
- unbind():当指令绑定的元素从 dom 中删除时触发