Vue内置指令与自定义指令大全

 更新时间:2025年10月24日 09:51:59   作者:咖啡の猫  
本文总结了Vue.js中的内置指令和自定义指令的使用方法和应用场景,内置指令包括v-bind、v-model、v-on、v-if/v-else/v-else-if、v-show、v-for、v-cloak和v-pre等,感兴趣的朋友跟随小编一起看看吧

一、Vue 内置指令大全

1.v-bind:动态绑定属性

用于动态绑定 HTML 属性或组件 prop。

<!-- 绑定 class -->
<div v-bind:class="{ active: isActive }"></div>
<!-- 缩写 -->
<img :src="imageURL" :alt="title">
<!-- 绑定对象 -->
<a v-bind="{ href, target, rel }">链接</a>

✅ 支持所有 HTML 属性和组件 prop。

2.v-model:双向数据绑定

简化表单元素与数据的同步。

<input v-model="message" placeholder="双向绑定">
<p>输入内容:{{ message }}</p>
<!-- 修饰符 -->
<input v-model.trim="username" />
<input v-model.number="age" />
<input v-model.lazy="search" />

🔁 v-model:value + @input 的语法糖。

3.v-on:事件监听

绑定 DOM 事件。

<button v-on:click="handleClick">点击</button>
<!-- 缩写 -->
<button @click="save">保存</button>
<!-- 修饰符 -->
<form @submit.prevent="onSubmit">
<input @keyup.enter="search" />
<button @click.once="doOnce">只触发一次</button>

✅ 常用修饰符:.prevent, .stop, .once, .self, .enter, .tab 等。

4.v-if/v-else/v-else-if:条件渲染

根据表达式真假决定是否渲染 DOM。

<div v-if="type === 'A'">类型 A</div>
<div v-else-if="type === 'B'">类型 B</div>
<div v-else>其他</div>

⚠️ 与 v-show 区别:v-if 是“真正”渲染/销毁,v-showdisplay: none 控制。

5.v-show:显示/隐藏切换

通过 CSS 控制显示状态。

<div v-show="isVisible">我被 v-show 控制</div>

✅ 适用于频繁切换的场景。

6.v-for:列表渲染

基于数组或对象渲染列表。

<li v-for="(item, index) in items" :key="item.id">
  {{ index }} - {{ item.name }}
</li>
<!-- 遍历对象 -->
<li v-for="(value, key) in user" :key="key">
  {{ key }}: {{ value }}
</li>

✅ 必须使用 :key 提升性能与稳定性。

7.v-cloak:防止闪现

解决页面加载时 Vue 未初始化导致的 {{ message }} 闪现问题。

<style>
  [v-cloak] { display: none; }
</style>
<div v-cloak>{{ message }}</div>

✅ 配合 CSS 使用,Vue 实例挂载后自动移除。

8.v-pre和v-once

  • v-pre:跳过该元素及其子元素的编译过程。
  • v-once:仅渲染一次,后续更新不重新渲染。
<span v-pre>{{ this will not be compiled }}</span>
<span v-once>{{ msg }}</span> <!-- msg 变化也不会更新 -->

✅ 用于静态内容或性能优化。

二、自定义指令:扩展 Vue 能力

当内置指令无法满足需求时,我们可以创建自定义指令

1. 注册方式

全局注册

// main.js
import { createApp } from 'vue'
const app = createApp({})
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

局部注册

<script>
export default {
  directives: {
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  }
}
</script>

2. 钩子函数(生命周期)

钩子触发时机
created指令绑定前
beforeMount元素挂载前
mounted元素插入父节点后(常用)
beforeUpdate组件更新前
updated组件更新后
beforeUnmount元素卸载前
unmounted元素卸载后(清理事件监听)

3. 钩子函数参数

每个钩子接收以下参数:

app.directive('demo', {
  mounted(el, binding, vnode, prevVnode) {
    // el: 指令绑定的元素
    // binding: 指令信息对象
    //   binding.value: 传入的值
    //   binding.arg: 参数,如 v-demo:arg
    //   binding.modifiers: 修饰符,如 v-demo.foo.bar
    // vnode: 虚拟节点
    // prevVnode: 上一个虚拟节点(更新时)
  }
})

三、自定义指令实战案例

案例 1:自动聚焦(v-focus)

app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})
<input v-focus placeholder="页面加载后自动聚焦">

案例 2:权限控制(v-permission)

// 假设用户权限存储在全局 store 或 config 中
const userPermissions = ['create', 'edit']
app.directive('permission', {
  mounted(el, binding) {
    const requiredPerm = binding.value
    if (!userPermissions.includes(requiredPerm)) {
      el.parentNode.removeChild(el) // 移除无权限的按钮
      // 或 el.style.display = 'none'
    }
  }
})
<button v-permission="'create'">新建用户</button>
<button v-permission="'delete'">删除用户</button> <!-- 会被移除 -->

✅ 企业级应用中常见需求。

案例 3:防重复点击(v-debounce)

let timer = null
app.directive('debounce', {
  mounted(el, binding) {
    const delay = binding.value || 1000
    el.addEventListener('click', () => {
      if (timer) return
      binding.instance[binding.arg] && binding.instance[binding.arg]()
      timer = setTimeout(() => {
        timer = null
      }, delay)
    })
  }
})
<template>
  <button v-debounce:submit="1000">提交</button>
</template>
<script>
export default {
  methods: {
    submit() {
      console.log('表单提交')
      // 发送请求
    }
  }
}
</script>

✅ 防止用户多次点击造成重复提交。

案例 4:图片懒加载(v-lazy)

const imgObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target
      img.src = img.dataset.src
      imgObserver.unobserve(img)
    }
  })
})
app.directive('lazy', {
  mounted(el, binding) {
    el.dataset.src = binding.value
    el.src = 'placeholder.jpg' // 占位图
    imgObserver.observe(el)
  },
  unmounted(el) {
    imgObserver.unobserve(el)
  }
})
<img v-lazy="imageUrl" alt="懒加载图片">

✅ 提升首屏加载性能。

四、Vue 3 Composition API 中的指令

setup() 中注册局部指令:

<script>
import { ref } from 'vue'
export default {
  setup() {
    const vFocus = {
      mounted: (el) => el.focus()
    }
    const count = ref(0)
    return {
      vFocus,
      count
    }
  }
}
</script>
<template>
  <input v-focus>
</template>

五、最佳实践与注意事项

✅ 推荐做法

  1. 优先使用组件而非指令:指令应专注于 DOM 操作。
  2. 复杂逻辑封装为 composables:避免指令过于臃肿。
  3. 及时清理资源:在 unmounted 中移除事件监听、定时器等。
  4. 命名语义化:如 v-permissionv-debounce-click

❌ 避免

  • 在指令中修改组件状态(binding.instance 不稳定)
  • 过度使用全局指令,造成命名污染
  • 忽略响应式更新(updated 钩子)

六、总结

类型指令用途
内置指令v-bindv-modelv-on数据绑定与事件
v-ifv-show条件渲染
v-for列表渲染
v-cloakv-pre编译控制
自定义指令v-focusv-permission扩展 DOM 能力
v-debouncev-lazy复用交互逻辑

📌 核心思想:内置指令解决通用问题,自定义指令解决特定场景的 DOM 操作。

七、结语

到此这篇关于Vue内置指令与自定义指令的文章就介绍到这了,更多相关Vue内置指令与自定义指令内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论