【Vue3】22-自定义指令

120 阅读1分钟

1. 自定义指令的生命周期

created:元素初始化的时候调用
beforeMount:指令绑定到元素后调用,只调用一次
mounted:元素插入父级 DOM 时调用
beforeUpdate:元素被更新之前调用
updated:元素被更新之后调用
beforeUnmount:元素被卸载之前调用
unmounted:元素被卸载之后调用,只调用一次

2. 自定义指令过程

2.1 定义指令

// 自定义指令规定用 v 开头
const vMove: Directive = {
    // 自定义指令的生命周期
    // 元素初始化的时候调用
    created() {
        console.log('created')
    },

    // 指令绑定到元素后调用,只调用一次
    beforeMount() {
        console.log('beforeMount')
    },

    // 元素插入父级 DOM 调用
    mounted(...args) {
        console.log('mounted', args)  // 如果不知道参数,则可以先统一接收打印看看
    },

    // 元素被更新之前调用
    beforeUpdate() {
        console.log('beforeUpdate')
    },

    // 元素更新完成后调用
    updated() {
        console.log('updated')
    },

    // 元素被移除前调用
    beforeUnmount() {
        console.log('beforeUnmount')
    },

    // 元素被移除后调用,只调用一次
    unmounted() {
        console.log('unmounted')
    },
}

2.2 使用指令

<!-- name 是属性名,{back....flag} 是属性值,modi 是修饰符,这些都可以在任何一个生命周期中获取到 -->
<dire v-move:name.modi="{background: 'skyblue', flag: flag}"></dire>

2.3 生命周期中接收的参数

image.png

参数 1:真实 DOM 元素
参数 2:自定义指令的相关信息,包括指令周期、属性名、属性新值、属性老值、修饰符
参数 3:更新之后的虚拟 DOM 节点
参数 4:更新之前的虚拟 DOM 节点,没有更新则为 null

2.4 可以在生命周期中做一些事情

// 元素插入父级 DOM 调用
mounted(el: HTMLElement, dir: DirectiveBinding<Dir>) {
    console.log('mounted')
    // console.log(el)
    // console.log(dir)
    // console.log(dir.value.background)
    // console.log(dir.modifiers.modi)
    el.style.background = dir.value.background  // 更改 DOM 元素的背景颜色
},

// 定义一个类型,用作 DirectiveBinding 的泛型,产生更友好的提示
type Dir = {
    background: string
}

3. 完整代码如下

<template>
    <button @click="flag = !flag">切换</button>
    <br>
    <!-- 测试元素的卸载 -->
    <!-- <dire v-if="flag" v-move:name.modi="{background: 'skyblue'}"></dire> -->
    
    <!-- 测试元素的更新 -->
    <dire v-move:name.modi="{background: 'skyblue', flag: flag}"></dire>
</template>

<script setup lang="ts">
import { Directive, DirectiveBinding, ref } from 'vue';
import Dire from './components/Dire.vue';

let flag = ref<boolean>(true)

type Dir = {
    background: string
}

// 自定义指令规定用 v 开头
const vMove: Directive = {
    // 自定义指令的生命周期
    // 元素初始化的时候调用
    created() {
        console.log('created')
    },
    
    // 指令绑定到元素后调用,只调用一次
    beforeMount() {
        console.log('beforeMount')
    },
    
    // 元素插入父级 DOM 调用
    // mounted(...args) {
    //     console.log('mounted', args)
    // },
        
    // 元素插入父级 DOM 调用
    mounted(el: HTMLElement, dir: DirectiveBinding<Dir>) {
        console.log('mounted')
        // console.log(el)
        // console.log(dir)
        // console.log(dir.value.background)
        // console.log(dir.modifiers.modi)
        el.style.background = dir.value.background
    },
    
    // 元素被更新之前调用
    beforeUpdate() {
        console.log('beforeUpdate')
    },
    
    // 元素更新完成后调用
    updated(...args) {
        console.log(args)
        console.log('updated')
    },
    
    // 元素被移除前调用
    beforeUnmount() {
        console.log('beforeUnmount')
    },
    
    // 元素被移除后调用,只调用一次
    unmounted() {
        console.log('unmounted')
    },
}
</script>