自定义指令是增强 Vue 组件的重要手段。常见的内置指令有: v-if、v-show、v-model、v-bind、v-on等。
本文将详细讲解如何创建和使用自定义指令,关注以下几个关键点:
1. 指令的钩子函数:类似于生命周期钩子函数。
2. 指令钩子函数中的参数:理解和使用这些参数是编写有效指令的关键。
3. 指令的逻辑处理:具体实现指令功能的核心。
1. 基本指令
我们通过一个简单的 v-focus 指令来入门,该指令可以让 input 组件在初始化渲染时自动获得焦点。
<script setup>
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<template>
<input v-focus />
</template>
如果你使用的是选项式 API,可以这样实现:
export default {
directives: {
focus: {
mounted(el) {
el.focus();
}
}
}
}
2. 指令钩子函数
自定义指令包括多个钩子函数,类似于组件的生命周期函数:
const myDirective = {
// 在绑定元素的 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) {}
}
3. 参数详解
指令的钩子函数会接收以下参数:
1. el:指令绑定的元素,用于直接操作 DOM。
2. binding:包含指令相关信息的对象。
(1). value:传递给指令的值,例如在 v-my-directive="1 + 1" 中,值是 2。
(2). oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。
(3). arg:传递给指令的参数(如果有),例如在 v-my-directive:foo 中,参数是 "foo"。
(4). modifiers:一个包含修饰符的对象,例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
(5). instance:使用该指令的组件实例。
(6). dir:指令的定义对象。
3. vnode:绑定元素的虚拟节点。
4. prevNode:之前的虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用。
例如,以下代码:
<div v-example:foo.bar="baz">
binding 参数会是一个如下的对象:
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
自定义指令的参数也可以是动态的:
<div v-example:[arg]="value"></div>
这里指令的参数会根据组件的 arg 数据属性响应式地更新。
4. 详解v-model
在实现双向绑定时,我们通常使用 v-model。其核心原理是结合 v-bind:value 和 v-on:input 来实现数据的同步。
Vue3 的 compiler-core 模块负责将模板编译为渲染函数,包括 AST 的生成、指令和表达式的处理、优化和代码生成等功能,适用于各种 JavaScript 环境。
而 compiler-dom 模块是针对浏览器环境的扩展,处理 DOM 元素的属性和事件编译,生成特定于浏览器环境的代码,用于开发基于 Vue3 的跨平台应用程序,如桌面和移动应用程序。
通过理解和运用这些钩子函数及参数,开发者可以创建功能强大且灵活的自定义指令,增强组件的交互性和可维护性。