在 Vue 中,指令(Directives) 是以 v- 开头的特殊属性,用于在模板中添加响应式行为。以下是面试中需要掌握的核心指令及要点:
一、常用内置指令
1. v-bind
作用:动态绑定 HTML 属性(如
class、style、href等)。简写:
:(冒号)。
2. v-model
作用:在表单控件上创建双向数据绑定(本质是
v-bind+v-on的语法糖)。适用元素:
<input>、<select>、<textarea>及组件。
3. v-for
作用:基于数组/对象循环渲染列表。
语法:
v-for="(item, index) in items",必须绑定:key(避免重复渲染问题)。
4. v-if / v-else-if / v-else
作用:条件渲染(动态添加/移除 DOM 元素)。
注意:
v-if有更高的切换开销,v-show有更高的初始渲染开销。
5. v-show
作用:条件显示(通过 CSS
display控制显示/隐藏,DOM 始终存在)。适用场景:频繁切换显示状态(如弹窗)。
6. v-on
作用:监听 DOM 事件。
简写:
@(如@click)。
7. v-html
作用:渲染 HTML 字符串(需注意 XSS 风险,避免渲染用户输入)。
8. v-text
作用:更新元素的
textContent(等同于{{ }}插值,但会覆盖子元素)。
9. v-once
作用:只渲染元素/组件一次,后续数据变化不再更新(用于优化静态内容)。
10. v-cloak
作用:解决 Vue 编译前“闪动”问题(结合 CSS
[v-cloak] { display: none }使用)。
二、指令对比(高频面试点)
v-if vs v-show
三、自定义指令
什么是自定义指令
自定义指令是用来操作 DOM 的。尽管 Vue 推崇数据驱动视图的理念,但并非所有情况都适合数据驱动。自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的 DOM 操作,并且是可复用的。
自定义指令的第二用处是用于集成第三方插件。我们知道任何软件开发领域都可以分为四层:底层是原生的API,上层是通用框架,再上层是通用组件,最上层才是具体的业务代码。一个通用框架,必须搭配一套完整的通用组件,才能真正奠定其江湖地位。
如何创建自定义指令
下面定义了一个 v-test 指令绑定数据 name。
<template>
<div class="hello">
<div v-test='name'></div>
</div>
</template>
<script>
export default {
data () {
return {
name:'我是名字',
}
},
directives:{
test:{
// 指令的定义
inserted: function (el, binding) {
// el为绑定元素,可以对其进行dom操作
console.log(binding) // binding 一个对象,包含很多属性
},
bind: function (el, binding, vnode) {
el.innerHTML =binding.value
}
}
},
created:function(){
},
mounted:function(){
},
methods:{
}
}
</script>我们可以全局自定义一个指令 v-red,来修改 HTML 元素的背景色为红色
<div id="box">
hello
<span v-red> welcome</span>
</div>
<script type="text/javascript">
Vue.directive('red',{
inserted: function(el){
el.style.background = 'red';
}
});
var vm = new Vue({
data:{
},
}).$mount('#box');
</script>自定义指令相关参数
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
钩子函数参数
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
指令钩子函数会被传入以下参数:
el:指令所绑定的元素,可以用来直接操作 DOM 。
binding:一个对象,包含以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 “1 + 1”。
arg:传给指令的参数,可选。例如 v-my-directive: foo 中,参数为 “foo”。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode: Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。
常见使用场景
1. 自动聚焦
Vue.directive('focus', {
inserted: (el) => el.focus()
})
// 使用:<input v-focus>2. 权限控制
Vue.directive('permission', {
inserted: (el, binding) => {
if (!hasPermission(binding.value)) {
el.parentNode.removeChild(el) // 无权限时移除元素
}
}
})
// 使用:<button v-permission="'admin'">删除</button>3. 图片懒加载
Vue.directive('lazy', {
inserted: (el, binding) => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
el.src = binding.value // 进入视口时加载图片
observer.unobserve(el)
}
})
observer.observe(el)
}
})
// 使用:<img v-lazy="imageUrl">4. 防抖/节流
Vue.directive('debounce', {
bind: (el, binding) => {
let timer = null
el.addEventListener('click', () => {
clearTimeout(timer)
timer = setTimeout(() => binding.value(), 500)
})
}
})
// 使用:<button v-debounce="handleClick">提交</button>函数简写
若只需 bind 和 update 时执行相同逻辑,可简写为函数:
Vue.directive('color', (el, binding) => {
el.style.color = binding.value
})
// 使用:<div v-color="'red'">Hello</div>动态指令参数(Vue 2.6.0+)
支持动态参数,实现灵活指令:
// dynamicColor 可以是 'color'/'background' 等
directives: {
color: (el, binding) => {
el.style[binding.arg] = binding.value // 动态设置样式属性
}
}四、面试回答模板
问题:Vue 中有哪些常用指令?它们的作用是什么?
回答:
Vue 的核心指令包括:
v-bind:动态绑定属性(简写:),如:src="url"。
v-model:表单双向绑定(本质是v-bind+v-on)。
v-for:循环渲染列表,必须加:key避免重复渲染问题。
v-if/v-show:条件渲染,v-if是动态增删 DOM,v-show是切换 CSSdisplay。
v-on:事件监听(简写@),如@click="handler"。
v-html:渲染 HTML(注意 XSS 风险)。
v-once:静态内容优化(只渲染一次)。
v-cloak:解决编译前闪动问题。
此外,Vue 支持自定义指令,通过钩子函数(如inserted)操作 DOM。自定义指令与组件的区别?
指令:直接操作 DOM,封装底层逻辑(如权限、DOM 事件)。
组件:可复用的 UI 单元,关注视图层和业务逻辑。
何时用自定义指令?
需直接操作 DOM(如聚焦、滚动)。
封复用性强的底层功能(如权限、懒加载、格式化)。
避免在组件中写过多 DOM 操作代码。
binding参数中的value和expression区别?
value:指令绑定值的计算结果(如v-color="1+1"→value: 2)。
expression:原始字符串表达式(如"1+1")。Vue 3 中自定义指令的变化?
钩子名调整(
inserted→mounted,bind→beforeMount)。支持 Fragment,指令可绑定到组件根节点外的元素。
新增
created钩子(在元素属性或事件监听器应用前调用)。
五、注意事项
v-for与v-if优先级:
Vue 2.x 中v-for优先级更高,会先循环再判断条件;Vue 3.x 中v-if优先级更高。避免同时使用,改用计算属性过滤数据。key的作用:
唯一标识节点,用于虚拟 DOM 的 Diff 算法,提升渲染效率。