Skip to content

自定义指令

除了 Vue 内置的一系列指令 (如 v-modelv-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: 之前的值,仅在 beforeUpdateupdated 中可用。
    • arg: 传递给指令的参数 (如果有)。例如 v-my-directive:foo 中,arg 的值是 "foo"
    • modifiers: 一个包含修饰符的对象 (如果有)。例如 v-my-directive.foo.bar 中,modifiers 的值是 { foo: true, bar: true }
  • vnode: 代表绑定元素的底层 VNode。
  • prevVnode: 代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdateupdated 钩子中可用。

示例:带参数的指令

让我们创建一个指令,它接收一个颜色值,并将元素的背景色设置为该值。

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 细节。

本站内容仅供学习和研究使用。