搜索文档
前言
本文将围绕 Vue3 学习自定义指令,如需回顾 Vue2 中的自定义指令可参考:Vue2-自定义指令, 本文末尾我将写一些在工作和日常开发中常用的自定义指令,并持续更新本文,每个案例均提供 Vue3 和 Vue2 两种写法。
介绍
一个自定义指令包含一些特定的生命周期钩子,钩子函数会接收到指令所绑定 Dom 元素和其他参数。
关于自定义指令的使用时机,官方的说法是:只有当所需功能只能通过直接的 DOM 操作来实现时,才应该使用自定义指令。 但我认为,如果某个需求复用率比较高,这种情况也可以使用自定义指令来实现,比如:按钮防抖等。
生命周期钩子
js
const myDirective = {
// 在绑定元素的 attribute 前或事件监听器应用前调用
created(el, binding, vnode) {},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode) {},
// 在绑定元素的父组件和所有子节点都挂载完成后调用
mounted(el, binding, vnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件和所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode) {}
}钩子函数参数:
el:指令绑定的Dom元素。binding:一个对象,属性如下:value:传递给指令的值oldValue:之前的值arg:传给指令的参数modifiers:一个包含修饰符的对象instance:使用指令的组件实例dir:指令的定义对象
vnode:代表绑定元素的底层VNode。prevVnode:代表之前的渲染中指令所绑定元素的VNode。仅在beforeUpdate和updated钩子中可用。
举个例子 🌰
vue
<script setup>
import {ref} from "vue";
let value = ref('张三');
</script>
<template>
<div class="app" v-demo:arg1.modifiers1="value"></div>
</template>此时的 binding 对象值为:
js
binding = {
value: '张三',
arg: 'arg1',
modifiers: {
modifiers1: true,
}
// ...
}全局注册
js
import {createApp} from 'vue';
import App from './App.vue';
const app = createApp(App);
app.directive('demo', {
// 在绑定元素的 attribute 前或事件监听器应用前调用
created(el, binding, vnode) {},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode) {},
// 在绑定元素的父组件和所有子节点都挂载完成后调用
mounted(el, binding, vnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件和所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode) {}
})
app.mount('#app');还有一种简单的写法,一个很常见的情况是只需要在 mounted 和 updated 上实现相同的行为,不需要其他钩子,这时我们可以这样写:
js
import {createApp} from 'vue';
import App from './App.vue';
const app = createApp(App);
app.directive('demo', (el, binding) => {
})
app.mount('#app');局部注册
setup 语法糖
vue
<script setup>
const vDemo = {
mounted(el, binding) {
console.log('el', el);
console.log('binding', binding);
},
}
</script>
<template>
<div class="app" v-demo="123"></div>
</template>vue
<script setup>
const vDemo = (el, binding) => {
console.log('el', el);
console.log('binding', binding);
}
</script>
<template>
<div class="app" v-demo="123"></div>
</template>组合式 API
vue
<script>
export default {
directives: {
demo: {
mounted(el, binding) {
console.log('el', el);
console.log('binding', binding);
},
}
}
}
</script>
<template>
<div class="app" v-demo="123"></div>
</template>vue
<script>
export default {
directives: {
demo(el, binding) {
console.log('el', el);
console.log('binding', binding);
},
}
}
</script>
<template>
<div class="app" v-demo="123"></div>
</template>