Skip to content

Vue 自定义插件合集

分类:Vue3
标签:VueWeb 前端
创建时间:2026年01月24日 09:02:51

前言

本文将围绕 Vue3 学习自定义指令,如需回顾 Vue2 中的自定义指令可参考:Vue2-自定义指令, 本文末尾我将写一些在工作和日常开发中常用的自定义指令,并持续更新本文,每个案例均提供 Vue3Vue2 两种写法。

介绍

一个自定义指令包含一些特定的生命周期钩子,钩子函数会接收到指令所绑定 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) {}
}

钩子函数参数:

  1. el:指令绑定的 Dom 元素。
  2. binding:一个对象,属性如下:
    • value:传递给指令的值
    • oldValue:之前的值
    • arg:传给指令的参数
    • modifiers:一个包含修饰符的对象
    • instance:使用指令的组件实例
    • dir:指令的定义对象
  3. vnode:代表绑定元素的底层 VNode
  4. prevVnode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdateupdated 钩子中可用。

举个例子 🌰

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');

还有一种简单的写法,一个很常见的情况是只需要在 mountedupdated 上实现相同的行为,不需要其他钩子,这时我们可以这样写:

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>

基于 MIT 许可发布