vue自定义指令(2.x丨3.x)可以帮助我们实现需要操作,比如防抖、节流、懒加载、输入框自动聚焦等等,使用起来非常方便,比如vue自带的v-text、v-html、v-show、v-if等等。
一、自定义指令分类
局部自定义指令:只在组件内有效
全局自定义指令:所有组件都有效
二、Vue2.x自定义指令钩子函数
bind:只会调用一次,指令第一次绑定到元素时会调用
inserted:被绑定元素插入父节点时调用。
update:元素第一次绑定不会触发,绑定的值发生更新触发,可能发生在其子节点更新之前。
componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
(1)bind与update区别
相同点:
dom插入都会调用,bind在inserted之前
异同点:
bind时父节点为null
inserted时父节点存在
bind是在dom树绘制前调用,inserted在dom树绘制后调用
(2)update与componentUpdated区别
组件更新都会调用,update在componentUpdated之前
update组件更新前的状态,componentUpdated组件更新后的状态
Vue.directive('focus', {
inserted: function (el) {
console.log(el.parentNode, 'inserted')
el.focus();
},
bind: function (el) {
console.log(el.parentNode, 'bind')
el.focus();
},
});
(3)钩子函数的参数
el:指令所绑定的元素,可以用来直接操作DOM。
binding:一个对象,包含以下property:
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编译生成的虚拟节点。移步VNodeAPI来了解更多详情。
oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用。
directives: {
style: {
bind(el, binding){
console.log(binding, 'binding')
el.style.fontSize = "30px";
el.style.color = "blue";
},
},
},
(4)全局自定义指令
使用Vue.directive(‘指令名称’,{钩子函数})
第一个参数为字符串,指令的名称
第二个参数是一个对象,用于接收指令的参数值
Vue.directive('style',{
bind(el){
el.style.fontSize="30px";
el.style.color="blue";
},
},
)
三、Vue3.x自定义指令钩子函数
(1)指令钩子函数
constmyDirective={
//在绑定元素的attribute前
//或事件监听器应用前调用
created(el,binding,vnode,prevVnode){
//下面会介绍各个参数的细节
},
//在元素被插入到DOM前调用
beforeMount(el,binding,vnode,prevVnode){},
//在绑定元素的父组件
//及他自己的所有子节点都挂载完成后调用
mounted(el,binding,vnode,prevVnode){},
//绑定元素的父组件更新前调用
beforeUpdate(el,binding,vnode,prevVnode){},
//在绑定元素的父组件
//及他自己的所有子节点都更新后调用
updated(el,binding,vnode,prevVnode){},
//绑定元素的父组件卸载前调用
beforeUnmount(el,binding,vnode,prevVnode){},
//绑定元素的父组件卸载后调用
unmounted(el,binding,vnode,prevVnode){}
}
(2)钩子函数参数
指令的钩子会传递以下几种参数:
el:指令绑定到的元素。这可以用于直接操作DOM。
binding:一个对象,包含以下属性。
value:传递给指令的值。例如在v-my-directive=“1+1”中,值是2。
oldValue:之前的值,仅在beforeUpdate和updated中可用。无论值是否更改,它都可用。
arg:传递给指令的参数(如果有的话)。例如在v-my-directive:foo中,参数是“foo”。
modifiers:一个包含修饰符的对象(如果有的话)。例如在v-my-directive.foo.bar中,修饰符对象是{foo:true,bar:true}。
instance:使用该指令的组件实例。
dir:指令的定义对象。
vnode:代表绑定元素的底层VNode。
prevNode:之前的渲染中代表指令所绑定元素的VNode。仅在beforeUpdate和updated钩子中可用。
(3)局部注册两种方式
<script lang="ts" setup>
//局部指令,变量名为驼峰命名(vFocus=v-focus)
constvFocus = {
mounted: (el: any) => {
el.focus()
console.log(el, '已经自动获得焦点')
}
}
</script>
<script lang="ts">
constvFocus = {
focus: {
mounted(el: any) {
el.focus();
console.log(el, "已经自动获得焦点");
}
},
};
exportdefault{
setup(){ },
directives: vFocus,
};
</script>
4)全局注册
组件A.vue
<input type="text" v-focus>
在directives文件夹新建focus.ts文件
constdirectives: any = {
mounted(el: any) {
el.focus();
el.value = '1'
}
}
exportdefault{
name: "focus",
directives
}
在directives文件夹新建index.js
importtype{App}from'vue'
importfocusfrom'./focus'
exportdefaultfunctioninstallDirective(app:App){
app.directive(focus.name,focus.directives);
}
main.ts文件
importdirectivesfrom'./directives'
constapp=createApp(App);
app.use(directives);