我想大家都接触过 v-on、v-show 等等指令,那自定义指令是什么呢?自定义指令就是你现在所想的那样,自己写一个自定义指令去操作 DOM 元素,以达到代码复用的目的。一提到代码复用,我想大家都能想到组件
,这里要注意的是自定义指令
和组件
的适用范围是不一样的。组件一般是我们复用一个结构、一个样式、一个逻辑。而自定义指令是当我们想对 dom 进行底层操作,而且底层操作是一样功能的时候,这时就可以使用自定义指令了。
注册指令分为全局注册
和局部注册
全局注册:
Vue.directive('focus', {/** */})
复制代码
局部注册:
const vm = new Vue({
el: '#app',
directives: {
focus: {/** */}
}
})
复制代码
例:写一个自动聚焦输入框的指令 v-focus
<body>
<div id="app">
<input type="text" v-focus>
</div>
<script>
//定义全局指令
Vue.directive("focus",{
inserted(el){
el.focus()
}
})
//定义局部指定
const vm = new Vue({
el: "#app",
data: {},
directives: {
focus: {
inserted(el) {
el.focus();
},
},
},
</script>
</body>
复制代码
但凡有 input 框需要自动聚焦,直接加上v-focus
就可以了。
☛注意:当全局指令和局部指令名字冲突的时候,会使用局部指令,所以在自定义指令的时候,要么全局,要么局部,二选一。
实现结果:
自定义指令生命周期钩子函数
接下来详细说明自定义指令配置对象,配置对象里面的东西并没有那么难,都是一些钩子函数,执行到某些时刻就执行的函数,也可以叫自定义指令生命周期钩子函数。
当把指令绑定到 dom 元素身上的时候就会执行,由于只绑定一次,所以只执行一次,在这里可以进行一次性的初始化设置。
inserted 被绑定的元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)
update 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
componentUpdated 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind 指令与 dom 元素解绑时调用(被绑定的 Dom 元素被 Vue 移除),只调用一次。
钩子函数的参数
el:指令所绑定的元素,可以用来直接操作 DOM
binding:对象,包含以下属性:
name : 指令名,不包括 v-前缀
value :指令的绑定值,例如:v-focus="1+1"中,绑定值为 2.
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可以使用。
expression:字符串形式的指令表达式。例如,v-focus="1+1",表达式为"1+1"
arg : 传给指令的参数,可选。例如,v-focus:src 中,参数为"src"
modifiers:一个包含修饰符的对象。例如,v-focus.obj.nice 中,修饰符对象为{obj: true, nice: true}
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
模拟 v-show 指令
<body>
<div id="app">
<input type="text" v-myshow="show" />
</div>
<script>
//模拟show指令
Vue.directive("myshow", {
bind(el, binding) {
const { value } = binding;
const display = value ? "" : "none";
el.style.display = display;
},
update(el,binding) {
const { value } = binding;
const display = value ? "" :"none";
el.style.display = display;
},
});
const vm = new Vue({
el: "#app",
data: {
show: true,
},
});
</script>
</body>
复制代码
结果演示:
如果在 bind 和 update 中触发相同的行为,而不关心其它钩子函数时,可以写成函数的形式,如下:
<body>
<div id="app">
<input type="text" v-myshow="show" />
</div>
<script>
//模拟show指令
Vue.directive("myshow",(el,binding)=>{
const { value } = binding;
const display = value ? "" : "none";
el.style.display = display;
});
const vm = new Vue({
el: "#app",
data: {
show: true,
},
});
</script>
</body>
复制代码
模拟 v-modle 指令
<body>
<div id="app">
<input type="text" v-mymodel="content" />{{ content }}
</div>
<script>
//模拟v-model指令
Vue.directive("mymodel",{
bind(el,binding,vnode){
const vm= vnode.context;
const {value,expression} = binding;
el.value = binding.value
el.oninput = function(){
const inputValue = el.value;
vm[expression] = inputValue;
}
},
update(el,binding){
const {value} = binding;
el.value = value
}
})
const vm = new Vue({
el: "#app",
data: {
content:"法医"
},
});
</script>
</body>
复制代码
结果演示:
评论