互联网技术 · 2024年3月3日

Vue 3自定义指令开发总结

这篇文章主要介绍了Vue 3自定义指令开发的相关总结,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下

什么是指令(directive)

在Angular和Vue中都有Directive的概念,我们通常讲Directive 翻译为“指令”。

在计算机技术中,指令是由指令集架构定义的单个的CPU操作。在更广泛的意义上,“指令”可以是任何可执行程序的元素的表述,例如字节码。

那么在前端框架Vue中“指令”到底是什么,他有什么作用呢?

在Vue开发中我们在模板中经常会使用v-model和v-show等以v-开头的关键字,这些关键字就是Vue框架内置的指令。通过使用v-model,可以获取实现DOM和数据的绑定;使用v-show,可以控制DOM元素显示。简而言之通过使用这些模板上的标签,让框架对DOM元素进行了指定的处理,同时DOM改变后框架可以同时更新指定数据。指令是Vue MVVM的基础之一。

指令的使用场景

除了使用内置的指令,Vue同样支持自定义指令,以下场景可以考虑通过自定义指令实现:

DOM的基础操作,当组件中的一些处理无法用现有指令实现,可以自定义指令实现。例如组件水印,自动focus。相对于用ref获取DOM操作,封装指令更加符合MVVM的架构,M和V不直接交互。

Highlight this text bright yellow

多组件可用的通用操作,通过使用组件(Component)可以很好的实现复用,同样通过使用组件也可以实现功能在组件上的复用。例如拼写检查、图片懒加载。使用组件,只要在需要拼写检查的输入组件上加上标签,遍可为组件注入拼写检查的功能,无需再针对不同组件封装新的支持拼写功能呢。

Vue 3如何自定义指令

Vue支持全局注册和局部注册指令。

全局注册注册通过app实例的directive方法进行注册。

let app = createApp(App)
app.directive(highlight, {
beforeMount(el, binding, vnode) {
el.style.background = binding.value
}
})

局部注册通过给组件设置directive属性注册

export default defineComponent({
name: “WebDesigner”,
components: {
Designer,
},
directives: {
highlight: {
beforeMount(el, binding, vnode) {
el.style.background = binding.value;
},
},
},
});

注册组件包含组件的名字,需要唯一和组件的一个实现对象,组册后即可在任何元素上使用了。

<p v-highlight=”yellow”>Highlight this text bright yellow</p>

自定义组件就是实现Vue提供的钩子函数,在Vue 3中钩子函数的生命周期和组件的生命周期类似:

created – 元素创建后,但是属性和事件还没有生效时调用。

beforeMount- 仅调用一次,当指令第一次绑定元素的时候。

mounted- 元素被插入父元素时调用.

beforeUpdate: 在元素自己更新之前调用

Updated – 元素或者子元素更新之后调用.

beforeUnmount: 元素卸载前调用.

unmounted -当指令卸载后调用,仅调用一次

每一个钩子函数都有如下参数:

el: 指令绑定的元素,可以用来直接操作DOM

binding: 数据对象,包含以下属性

instance: 当前组件的实例,一般推荐指令和组件无关,如果有需要使用组件上下文ViewModel,可以从这里获取

value: 指令的值,即上面示例中的“yellow“

oldValue: 指令的前一个值,在beforeUpdate和Updated 中,可以和value是相同的内容。

arg: 传给指令的参数,例如v-on:click中的click。

modifiers: 包含修饰符的对象。例如v-on.stop:click 可以获取到一个{stop:true}的对象

vnode: Vue 编译生成的虚拟节点,

prevVNode: Update时的上一个虚拟节点

Vue 2 指令升级

指令在Vue3中是一个Breaking Change,指令的钩子函数名称和数量发生了变化。Vue3中为指令创建了更多的函数,函数名称和组件的生命周期一致,更易理解。

以下是变化介绍

Vue 3自定义指令开发的相关总结 -

另一个变化是组件上下文对象的获取方式发生了变化。一般情况下推荐指令和组件实例相互独立,从自定义指令内部去访问组件实例,那可能说明这里不需要封装指令,指令就是组件本事的功能。但是可能的确有某些场景需要去获取组件实例。

在Vue 2中通过vnode参数获取

bind(el, binding, vnode) {
  const vm = vnode.context
}

在Vue 3中 通过binding参数获取

mounted(el, binding, vnode) {
  const vm = binding.instance
}

Vue 3 自定义指令实例 – 输入拼写检查

这里使用Plugin的方式注入指令。

新建SpellCheckPlugin.ts,声明插件,在插件的install方法中注入指令

import { App } from vue
 
function SpellCheckMain(app: App, options: any) {
//
}
 
export default {
    install: SpellCheckMain
}

SpellCheckMain方法实现组件以及,拼写检查方法,具体拼写检查规则可以根据业务或者使用其他插件方法实现

function SpellCheckMain(app: App, options: any) {
    const SpellCheckAttribute = “spell-check-el”;
 
    let SpellCheckTimer: Map<string, number> = new Map();
    let checkerId = 0;
    function checkElement(el: HTMLElement) {
        let attr = el.getAttribute(SpellCheckAttribute);
        if (attr) {
            clearTimeout(SpellCheckTimer.get(attr));
            let timer = setTimeout(() => { checkElementAsync(el) }, 500);
            SpellCheckTimer.set(attr, timer)
        }
    }
    function checkText(words?: string | null): [string?] {
        if (!words) {
            return [];
        }
        let errorWordList: [string?] = [];
        try {
    &nbsp

OpenMagic API

Need more than content? Move into the product flow.

If you are here for model access, pricing, developer docs, or the future API console, the dedicated product path now lives on api.openmagic.ai.

登录免费注册