Vue 指令系统

v-ifv-model 和自定义指令是如何工作的?

指令是带有 v- 前缀的特殊模板属性,用于把响应式数据或行为绑定到 DOM、组件或模板结构上:

<input v-model="keyword" />
<button v-if="canSubmit" @click="submit">提交</button>

1. 常见内置指令

指令作用
v-if条件创建和销毁节点
v-show通过 CSS display 控制显示隐藏
v-for列表渲染
v-bind / :绑定属性或 prop
v-on / @绑定事件
v-model表单值与状态同步
v-slot / #使用插槽
v-html插入 HTML 字符串
v-once只渲染一次
v-memo条件满足时跳过子树更新

2.v-ifv-show

<Panel v-if="visible" />
<Panel v-show="visible" />
  • v-if:条件为 false 时不创建或会销毁节点,切换成本高,初始条件为 false 时可以避免创建。
  • v-show:节点始终存在,只切换 display,适合频繁切换。

选择时关注两个维度:初始渲染成本和切换频率,而不是简单记忆“少用 v-if”。

3.v-for 与 key

<TodoItem
  v-for="todo in todos"
  :key="todo.id"
  :todo="todo"
/>

key 用于标识同级节点身份,帮助 Vue 正确复用组件实例和 DOM。动态列表中不建议使用 index,尤其是列表会插入、删除、排序或过滤时。

v-ifv-for 同时出现在一个元素上时,应避免依赖它们的优先级,优先使用计算属性过滤数据或包一层模板:

<template v-for="todo in visibleTodos" :key="todo.id">
  <TodoItem :todo="todo" />
</template>

4.v-bindv-on

<button :disabled="loading" @click="submit">
  {{ loading ? '提交中' : '提交' }}
</button>

动态绑定本质上会进入组件或元素的 props / event 处理流程。可以使用对象绑定:

<button v-bind="buttonProps" />

修饰符会改变指令行为,例如:

<form @submit.prevent="submit" />
<div @click.stop="handleClick" />
<input v-model.trim="name" />

5.v-model 的本质

在原生输入框上,v-model 可以理解为 value 绑定加 input 事件监听:

<input v-model="name" />

近似于:

<input :value="name" @input="name = $event.target.value" />

在 Vue 3 组件上,默认对应 modelValue prop 和 update:modelValue 事件:

<CustomInput
  :model-value="name"
  @update:model-value="name = $event"
/>

6.v-html 的安全问题

v-html 会把字符串作为 HTML 插入 DOM,不会自动替你清理不可信内容:

<div v-html="trustedHtml" />

如果内容来自用户输入或外部接口,应先经过可靠的 HTML 清洗,避免 XSS。能使用普通插值时,优先使用插值,因为插值默认会进行文本转义。

7. 自定义指令

自定义指令适合封装与 DOM 直接交互的可复用逻辑,例如自动聚焦:

const vFocus = {
  mounted(element) {
    element.focus();
  },
};
<input v-focus />

常用钩子包括:

  • created
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeUnmount
  • unmounted

指令应聚焦 DOM 行为;如果逻辑主要是状态、请求或跨组件通信,通常更适合写成组件或 composable。

8. 常见误区

  • v-show 不会销毁组件,v-if 可能销毁并重新创建组件。
  • v-model 不是双向绑定黑盒,本质是值传递和事件回传。
  • v-html 不是安全的富文本渲染方案。
  • 自定义指令不是所有逻辑复用场景的替代品。
  • 指令修饰符由编译器转换成对应的事件、属性或运行时逻辑。

面试总结

Vue 指令是模板编译器识别的特殊语法。编译阶段会把 v-ifv-forv-bindv-onv-model 等转换成条件、列表、props 和事件处理逻辑;自定义指令则通过生命周期钩子封装 DOM 交互。v-if 控制节点创建销毁,v-show 只控制显示状态,v-model 本质是 value 与事件的组合。