Vue3 自定义指令
Vue3 内置了 v-if、v-model 等指令,但项目里常出现"多处需要同一段 DOM 行为"的需求,比如输入框自动聚焦、按钮设置权限、图片懒加载。自定义指令能把这类直接操作 DOM 的逻辑封装起来,一处定义、到处复用,让模板保持简洁。
什么场景适合指令
指令与组件要区分开:组件是一块"带模板的界面",而指令是"直接操纵 DOM 的小工具"。当需求只涉及原生 DOM(如 focus、样式、监听原生事件)而不需要模板与响应式数据时,自定义指令更轻量合适。
注册一个指令
在 <script setup> 中,任何以 v 开头的变量都会被自动当成自定义指令。例如定义 const vFocus:
<template>
<input v-focus placeholder="自动聚焦的输入框" />
</template>
<script setup>
const vFocus = {
mounted: (el) => el.focus(),
// 效果:元素挂载到页面后立即获得焦点,可直接打字
}
</script>
mounted 钩子在元素被插入 DOM 后执行,此时 el 已经可用,是最常用的时机。
指令对象与 binding
指令对象可以定义多个生命周期钩子,其中 mounted 与 updated 最常用。回调的第二个参数 binding 携带指令的完整信息:value 是等号右侧的值,arg 是冒号后的参数,modifiers 是修饰符对象。
<script setup>
const vHighlight = {
mounted: (el, binding) => {
el.style.backgroundColor = binding.value // 指令值,如 'yellow'
},
}
</script>
用法:<p v-highlight="'yellow'">,则 binding.value 为字符串 'yellow',元素背景变黄。
参数与修饰符的完整示例
综合使用值、参数与修饰符,可以让一个指令适应多种调用方式:
<template>
<p v-tip:right.red="'复制成功'">悬停查看提示</p>
</template>
<script setup>
const vTip = {
mounted: (el, binding) => {
el.onmouseenter = () => {
const pos = binding.arg || 'bottom' // 参数:'right'
const color = binding.modifiers.red ? 'red' : '#333' // 修饰符
const text = binding.value // 值:'复制成功'
console.log(`${pos} 位置显示:${text}(${color}色)`)
// 效果:鼠标悬停时控制台按调用方式打印
}
},
}
</script>
小结
自定义指令把"操作 DOM 的小动作"从业务代码中剥离出来:在 <script setup> 里定义 v 开头的变量即完成注册,在 mounted、updated 钩子中操作元素,通过 binding 读取值、参数与修饰符。页面级复杂逻辑请优先交给组件,指令只负责它擅长的精细 DOM 控制。