认识
一、认识
除了 Vue
内置的一系列指令 (比如 v-model
或 v-show
) 之外,Vue
还允许你注册自定义的指令 (Custom Directives
)。自定义指令主要是为了重用涉及普通元素的底层 DOM
访问的逻辑(提供让我们去操作 DOM
的能力)。
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。这些钩子函数将来在不同的时期被调用执行,自定义指令跟 Vue3
底层内置的指令运行原理是一致的。
二、语法
2.1 对象式
const directive = {
created(el, binding, vnode, prevVnode) {
},
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) {}
}
2.2 函数式
对于自定义指令来说,一个很常见的情况是仅仅需要在 mounted
和 updated
上实现相同的行为,除此之外并不需要其他钩子。这种情况下我们可以直接用一个函数来定义指令
const directive = (el,binding)=>{
}
三、用法
3.1 组合式组件指令
在组合式中, 任何以 v
开头的驼峰式命名的变量都可以被用作一个自定义指令。
<template>
<div id="div-app">
<input v-auto-focus />
</div>
</template>
<script setup>
const vAutoFocus = {
mounted: el => el.focus()
};
</script>
3.2 选项式组件指令
在选项式中, 自定义指令需要通过 directives
选项注册
<template>
<div id="div-app">
<input v-auto-focus />
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
directives: {
autoFocus: {
mounted(el) {
el.focus();
}
}
},
setup() {}
});
</script>
3.3 全局自定义指令
- main.js
- App.vue
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
const app = createApp(App);
app.directive('vAutoFocus', {
mounted: el => {
return el.focus();
}
});
app.mount('#app');
<template>
<div>
<input v-auto-focus />
</div>
</template>
3.4 全局插件自定义指令
- vAutoFocus.ts
- main.ts
- app.vue
import { App } from 'vue';
const vAutoFocus = {
install(app: App<Element>, _options: any) {
app.directive('autoFocus', {
mounted: el => {
return el.focus();
}
});
}
};
export default vAutoFocus;
import App from './App.vue';
import { createApp } from 'vue';
import vAutoFocus from './directives/vAutoFocus';
const app = createApp(App);
app.use(vAutoFocus, {});
app.mount('#app');
<template>
<div>
<input v-auto-focus />
</div>
</template>
四、指令数据
4.1 指令参数
指令传参如下:
<div v-xxx:arg="yy"></div>
指令接收如下
{
arg: 'arg',
modifiers: { },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
4.2 指令修饰符
指令参数与修饰符如下:
<div v-xxx:arg.modifiers="yy"></div>
指令接收如下
{
arg: 'arg',
modifiers: { modifiers: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
4.3 指令动态数据
<div v-example:foo.bar="baz">
<div v-example:[arg]="baz"></div> // 这里指令的参数会基于组件的 arg 数据属性响应式地更新。
binding
的参数情况:
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
五、指令钩子
一个指令的定义对象可以提供几种钩子函数 (都是可选的), 指令的钩子会传递以下几种参数:
-
el
: 指令绑定到的元素。这可以用于直接操作DOM
。 -
binding
: 一个对象,包含以下属性。-
value
: 传递给指令的值。例如在v-my-directive="1 + 1"
中,值是2
。 -
oldValue
: 之前的值,仅在beforeUpdate
和updated
中可用。无论值是否更改,它都可用。 -
arg
: 传递给指令的参数 (如果有的话)。例如在v-my-directive:foo
中,参数是"foo"
。 -
modifiers
: 一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar
中,修饰符对象是{ foo: true, bar: true }
。 -
instance
: 使用该指令的组件实例。 -
dir
: 指令的定义对象
-
-
vnode
: 代表绑定元素的底层VNode
。 -
prevNode
: 之前的渲染中代表指令所绑定元素的VNode
。仅在beforeUpdate
和updated
钩子中可用。
注意: 除了 el
外,其他参数都是只读的,不要更改它们。若你需要在不同的钩子间共享信息,推荐通过元素的 dataset attribute
实现。
4.1 created
created
在绑定元素的 attribute
前或事件监听器应用前调用
语法
created(el, binding, vnode, prevVnode) {
}
4.2 beforeMount
beforeMount
在元素被插入到 DOM
前调用
语法
beforeMount(el, binding, vnode, prevVnode) {},
4.3 mounted
mounted
在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
语法
mounted(el, binding, vnode, prevVnode) {}
4.4 beforeUpdate
beforeUpdate
绑定元素的父组件更新前调用
语法
beforeUpdate(el, binding, vnode, prevVnode) {}
4.5 updated
updated
在绑定元素的父组件及他自己的所有子节点都更新后调用
语法
updated(el, binding, vnode, prevVnode) {}
4.6 beforeUnmount
beforeUnmount
绑定元素的父组件卸载前调用
语法
beforeUnmount(el, binding, vnode, prevVnode) {},
4.7 unmounted
unmounted
绑定元素的父组件卸载后调用
语法
unmounted(el, binding, vnode, prevVnode) {}