← 返回目录

第 3 卷

第 3 / 12 卷日期:

◦ 示例: <input v-model="msg"> 会被编译为 <input :value="msg"

二、不同场景的实现细节

• 表单元素: v-model 根据元素类型自动匹配属性和事件(文本框: value + input;复选

框: checked + change);

• 自定义组件: v-model 是 modelValue prop 和 update:modelValue 事件的语法糖,父

组件通过 v-model 传递数据,子组件通过 emit('update:modelValue', 新值) 更新父组件数据,实现双向绑定。

9. Vue数据变化时视图的更新机制(即时/异步)

Vue中数据对象属性值改变时,视图更新是异步的,而非即时的。

一、核心原因

Vue采用异步更新队列的设计,目的是:

  1. 避免重复更新:若在同一事件循环中多次修改同一数据(或多个数据),Vue会将多次更新请求合

并为一次,减少DOM操作次数,提升性能;

  1. 避免中间状态展示:若同步更新,可能导致视图展示数据的中间状态(如多次修改数据,视图频繁

闪烁),异步更新可确保视图最终展示的是数据的最终状态。

二、视图更新的具体机制

  1. 触发更新:当响应式数据变化时, trigger 函数会触发对应的 Effect(如组件渲染副作

用),Vue不会立即执行 Effect,而是将其加入异步更新队列;

  1. 队列去重:Vue会对更新队列进行去重处理(同一组件的 Effect 只会被添加一次),避免重复渲

染;

  1. 执行队列:Vue会在当前事件循环的微任务阶段(优先)或下一个宏任务阶段执行更新队列中的

Effect,完成组件渲染和DOM更新;

◦ Vue2:基于 Promise.then(微任务)实现异步队列,兼容环境下会降级为 setTimeout

(宏任务);

◦ Vue3:基于 queuePostFlushCb 函数,优先使用 Promise.then,其次是

MutationObserver,最后是 setTimeout;

  1. 更新完成:异步队列执行完毕后,视图更新完成,若需要在视图更新后执行逻辑,可使用

$nextTick(Vue2)或 nextTick(Vue3)。

4this.msg = '3' 5// 视图最终展示'3',仅执行一次DOM更新

10. Vue对象/数组的属性变化监听实现原理

Vue对对象和数组的监听机制做了差异化设计,适配两者的特性,核心实现如下:

一、对象属性变化的监听原理

Vue2 实现

  1. 递归遍历对象的所有已有属性,对每个属性调用 Object.defineProperty,定义 get(依

赖收集)和 set(依赖触发)拦截器;

  1. 当访问对象属性时,触发 get 拦截,收集当前副作用(Watcher);
  2. 当修改对象属性值时,触发 set 拦截,通知依赖集合(Dep)中的Watcher更新;
  3. 对于新增属性:无法自动监听,需通过 Vue.set(obj, key, value) 手动为新增属性添加

Object.defineProperty 拦截,并触发依赖更新;

  1. 对于删除属性:无法自动监听,需通过 Vue.delete(obj, key) 手动删除属性并触发依赖更

新;

  1. 对于嵌套对象:递归遍历嵌套对象,逐层为属性添加拦截,实现深层响应式。

Vue3 实现

  1. 通过 Proxy 创建对象的代理,拦截整个对象的操作,无需递归遍历已有属性;

2.get 拦截器:访问对象属性时,收集依赖;若属性值是嵌套对象,按需对嵌套对象创建 Proxy (懒代理),实现深层响应式;

3.set 拦截器:修改属性值(或新增属性)时,触发依赖更新,并返回 true 表示操作成功;

4.deleteProperty 拦截器:删除对象属性时,触发依赖更新,并返回 true 表示操作成功;

  1. 无需手动处理新增/删除属性,原生支持深层对象监听,性能更优。

二、数组属性变化的监听原理

Vue2 实现(缺陷明显,需特殊处理)

  1. 重写数组原型方法:Vue2会创建一个数组原型的“副本”,重写其中7个变异方法(push、pop、
  1. 无法监听的场景:
  • 数组索引修改(如 arr[0] = 123);
  • 数组长度修改(如 arr.length = 0);
  • 非变异方法调用(如 arr.slice(0, 1),不会修改原数组);
  1. 对于上述无法监听的场景,需通过 Vue.set(arr, index, value) 手动触发更新。

Vue3 实现(原生支持,无需特殊处理)

  1. 通过 Proxy 拦截数组的所有操作,无需重写原型方法;

2.get 拦截器:访问数组元素(索引)、长度、调用数组方法时,收集依赖;

3.set 拦截器:修改数组索引值、修改数组长度时,触发依赖更新;

  1. 无论调用何种数组方法(变异/非变异)、修改索引/长度,都能被 Proxy 感知,原生支持数组的

全量变化监听,无需手动干预。

11. keep-alive组件:作用、实现机制、缓存内容

一、 keep-alive的核心作用

keep-alive 是Vue内置的抽象组件(自身不会渲染为真实DOM),核心作用是:

  1. 缓存组件实例:当组件在 keep-alive 内被切换时,不会被销毁(即不执行

unmounted / destroyed 生命周期),而是被缓存起来;

  1. 保留组件状态:缓存后的组件再次激活时,会保留其之前的状态(如表单输入内容、滚动条位置

等),无需重新初始化数据;

  1. 提升性能:避免组件频繁创建( mounted / created)和销毁,减少DOM操作和数据请求开

销,提升页面切换流畅度。

二、实现机制

keep-alive 的实现依赖Vue的组件生命周期和缓存容器,核心流程如下:

  1. 缓存容器: keep-alive 内部维护两个缓存容器(对象/Map):
  • cache:存储缓存的组件实例(key:组件的 name 或 cid,value:组件实例VNode);

◦ keys:存储缓存组件的key列表,用于控制缓存上限( max 属性),实现LRU(最近最少使

用)缓存策略;

全站分卷索引 · 12 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷