自定义指令
除了 Vue 内置的一系列指令 (如 v-model 或 v-show),Vue 也允许你注册自己的自定义指令。自定义指令的主要应用场景是对普通 DOM 元素进行底层操作。
一个常见的例子是,当页面加载时,让某个输入框自动获得焦点。虽然可以手动通过 ref 来实现,但使用自定义指令可以更好地封装和复用这个行为。
创建一个自定义指令
在 <script setup> 中,任何以 v 开头的驼峰式命名的变量都可以被用作一个自定义指令。在下面的例子中,vFocus 这个指令可以在模板中以 v-focus 的形式使用。
vue
<script setup>
// 在模板中启用 v-focus
const vFocus = {
// 当被绑定的元素挂载到 DOM 中时……
mounted: (el) => {
// 聚焦元素
el.focus()
}
}
</script>
<template>
<input v-focus />
</template>指令的生命周期钩子
一个指令定义对象可以提供如下几个钩子函数 (都是可选的):
created: 在绑定元素的 attribute 或事件监听器被应用之前调用。beforeMount: 当指令第一次被绑定到元素并且在挂载父组件之前调用。mounted: 在绑定元素的父组件被挂载后调用。beforeUpdate: 在更新包含组件的 VNode 之前调用。updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。beforeUnmount: 在卸载绑定元素的父组件之前调用。unmounted: 当指令与元素解除绑定且父组件已卸载时调用。
钩子函数的参数
指令钩子会传递以下几种参数:
el: 指令所绑定的元素,可以用来直接操作 DOM。binding: 一个对象,包含以下 property:value: 指令的绑定值。例如v-my-directive="1 + 1"中,value的值是2。oldValue: 之前的值,仅在beforeUpdate和updated中可用。arg: 传递给指令的参数 (如果有)。例如v-my-directive:foo中,arg的值是"foo"。modifiers: 一个包含修饰符的对象 (如果有)。例如v-my-directive.foo.bar中,modifiers的值是{ foo: true, bar: true }。
vnode: 代表绑定元素的底层 VNode。prevVnode: 代表之前的渲染中指令所绑定元素的 VNode。仅在beforeUpdate和updated钩子中可用。
示例:带参数的指令
让我们创建一个指令,它接收一个颜色值,并将元素的背景色设置为该值。
vue
<script setup>
const vBackgroundColor = {
mounted: (el, binding) => {
// binding.value 是传递给指令的值
el.style.backgroundColor = binding.value
}
}
</script>
<template>
<div v-background-color="'red'">This will have a red background.</div>
<p v-background-color="'#cba'">And this one, a light purple.</p>
</template>全局注册指令
如果你希望在应用的任何组件中都能使用某个指令,可以在 main.js 中进行全局注册。
main.js
js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
mounted: (el) => {
el.focus()
}
})
app.mount('#app')自定义指令提供了一种强大的方式来封装可复用的 DOM 操作,使得我们的组件逻辑可以更专注于数据和业务,而不是底层的 DOM 细节。