vue 指令

在 Vue 中,指令(Directive) 是带有 v- 前缀的特殊 HTML 特性,用来响应式地修改 DOM 。Vue 3 中指令分为 内置指令自定义指令,以及配合 Composition API 的新用法。


一、Vue 3 常见内置指令

1️⃣ 条件渲染

vue 复制代码
<div v-if="isVisible">显示</div>
<div v-else-if="loading">加载中</div>
<div v-else>隐藏</div>

<div v-show="isVisible">切换显示</div>
指令 区别
v-if 真正的条件渲染(销毁 / 重建 DOM)
v-show 仅切换 display CSS

2️⃣ 列表渲染

vue 复制代码
<ul>
  <li v-for="(item, index) in list" :key="item.id">
    {{ index }} - {{ item.name }}
  </li>
</ul>

必须加 :key


3️⃣ 事件绑定

vue 复制代码
<button @click="handleClick">点击</button>
<button @click.stop="stopPropagation">阻止冒泡</button>
<button @click.prevent="submit">阻止默认</button>
<button @click.once="onlyOnce">只触发一次</button>

@v-on: 的简写


4️⃣ 双向绑定

vue 复制代码
<input v-model="name" />

<!-- 等价写法 -->
<input :value="name" @input="name = $event.target.value" />

修饰符:

vue 复制代码
<input v-model.trim="name" />
<input v-model.number="age" />
<input v-model.lazy="msg" />

5️⃣ 属性绑定

vue 复制代码
<img :src="imgUrl" />
<div :class="{ active: isActive }"></div>
<div :style="{ color: textColor }"></div>

6️⃣ 文本插值 & HTML

vue 复制代码
<span>{{ message }}</span>
<span v-text="message"></span>
<span v-html="htmlContent"></span>

⚠️ v-html 有 XSS 风险


7️⃣ 其他常用指令

vue 复制代码
<div v-pre>{{ 不会被编译 }}</div>
<div v-cloak>{{ 防止闪屏 }}</div>
<div v-once>只渲染一次</div>

二、自定义指令(Vue 3)

1️⃣ 全局注册

js 复制代码
// main.js
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})
vue 复制代码
<input v-focus />

2️⃣ 局部注册

vue 复制代码
<script setup>
const vFocus = {
  mounted(el) {
    el.focus()
  }
}
</script>

<template>
  <input v-focus />
</template>

3️⃣ 指令钩子(Vue 3)

js 复制代码
app.directive('example', {
  created(el) {},
  beforeMount(el) {},
  mounted(el) {},
  beforeUpdate(el) {},
  updated(el) {},
  beforeUnmount(el) {},
  unmounted(el) {}
})

4️⃣ 带参数的指令

vue 复制代码
<p v-color="'red'">文字变红</p>
js 复制代码
app.directive('color', {
  mounted(el, binding) {
    el.style.color = binding.value
  },
  updated(el, binding) {
    el.style.color = binding.value
  }
})

5️⃣ 修饰符支持

vue 复制代码
<input v-format.limit10 />
js 复制代码
app.directive('format', {
  mounted(el, binding) {
    if (binding.modifiers.limit10) {
      el.maxLength = 10
    }
  }
})

三、常用自定义指令示例

✅ 防抖指令

js 复制代码
app.directive('debounce', {
  mounted(el, binding) {
    let timer
    el.addEventListener('click', () => {
      clearTimeout(timer)
      timer = setTimeout(() => {
        binding.value()
      }, 500)
    })
  }
})
vue 复制代码
<button v-debounce="submit">提交</button>

✅ 权限指令

js 复制代码
app.directive('permission', {
  mounted(el, binding) {
    const hasPerm = checkPermission(binding.value)
    if (!hasPerm) {
      el.parentNode?.removeChild(el)
    }
  }
})
vue 复制代码
<button v-permission="'user:add'">新增用户</button>

四、指令 vs 组件

场景 推荐
DOM 行为(焦点、拖拽、权限) 指令
UI + 逻辑复用 组件
表单交互 v-model / 组件

五、Vue 3 指令变化总结

✅ 生命周期改为 挂载/更新/卸载

✅ 支持 v-bind / v-on 动态参数

✅ 更适合与 Composition API 结合