当前位置:首页 > VUE

vue diff实现

2026-01-12 23:22:45VUE

Vue 的 Diff 算法实现

Vue 的虚拟 DOM Diff 算法(称为 "patch" 过程)通过高效比较新旧虚拟节点(VNode)来最小化 DOM 操作。其核心思想是基于以下策略:

同层级比较

Vue 仅在同一层级的虚拟节点间比较,不跨层级递归。若节点类型不同(如 div 变为 span),直接销毁旧节点并创建新节点。

双端比较(针对列表)

对于列表节点(如 v-for),Vue 使用 双端指针(头尾共 4 个指针)进行快速比对,优先处理以下场景:

  1. 头头匹配:新旧列表的头节点相同。
  2. 尾尾匹配:新旧列表的尾节点相同。
  3. 头尾匹配:旧头与新尾相同(说明节点移动到尾部)。
  4. 尾头匹配:旧尾与新头相同(说明节点移动到头部)。

若无匹配,则通过 key 查找旧节点中是否存在可复用的节点。

Key 的作用

key 是唯一标识,帮助 Vue 识别节点的稳定性。若 key 相同且节点类型相同,则复用 DOM 元素,仅更新属性或子节点。

核心代码逻辑示例

以下是简化后的 Diff 流程代码(非完整源码):

function patch(oldVnode, newVnode) {
  // 类型不同,直接替换
  if (oldVnode.tag !== newVnode.tag) {
    replaceNode(oldVnode, newVnode);
    return;
  }

  // 复用 DOM 元素
  const el = (newVnode.el = oldVnode.el);

  // 更新属性
  updateProps(el, oldVnode.props, newVnode.props);

  // 处理子节点
  if (oldVnode.children && newVnode.children) {
    updateChildren(el, oldVnode.children, newVnode.children);
  } else if (newVnode.children) {
    // 旧无子,新有子:添加
    appendChildren(el, newVnode.children);
  } else if (oldVnode.children) {
    // 旧有子,新无子:删除
    removeChildren(el);
  }
}

function updateChildren(parentEl, oldCh, newCh) {
  let oldStartIdx = 0, newStartIdx = 0;
  let oldEndIdx = oldCh.length - 1, newEndIdx = newCh.length - 1;

  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    // 双端比较逻辑...
    if (sameVnode(oldCh[oldStartIdx], newCh[newStartIdx])) {
      patch(oldCh[oldStartIdx], newCh[newStartIdx]);
      oldStartIdx++;
      newStartIdx++;
    } else if (sameVnode(oldCh[oldEndIdx], newCh[newEndIdx])) {
      patch(oldCh[oldEndIdx], newCh[newEndIdx]);
      oldEndIdx--;
      newEndIdx--;
    }
    // 其他情况处理...
  }
}

性能优化策略

  1. 静态节点提升:编译阶段标记静态节点,Diff 时直接跳过。
  2. 事件缓存:避免重复绑定事件处理函数。
  3. 异步更新队列:通过 nextTick 批量处理 DOM 更新,减少重排重绘。

与 React Diff 的区别

  1. 列表策略:Vue 使用双端比较,React 使用单向遍历。
  2. 组件复用:Vue 通过 key 和组件类型匹配复用,React 仅依赖 key
  3. 移动逻辑:Vue 更擅长处理节点位置变化,React 倾向于按索引顺序更新。

vue diff实现

标签: vuediff
分享给朋友:

相关文章

vue实现选择本地文件

vue实现选择本地文件

实现文件选择功能 在Vue中实现本地文件选择可以通过HTML原生的<input type="file">元素实现。创建一个基本的文件选择组件: <template> &l…

vue实现用户信息表

vue实现用户信息表

Vue 实现用户信息表的方法 使用 Vue CLI 创建项目 安装 Vue CLI 并初始化项目: npm install -g @vue/cli vue create user-info-tabl…

vue自己实现下拉导航

vue自己实现下拉导航

实现下拉导航的基本思路 在Vue中实现下拉导航,可以通过结合Vue的响应式数据和事件绑定特性来完成。主要思路是利用v-show或v-if控制下拉菜单的显示与隐藏,并通过鼠标事件或点击事件触发状态变化。…

vue实现input

vue实现input

Vue 实现 Input 输入框的方法 基本双向绑定 使用 v-model 指令实现双向数据绑定,适用于大多数表单场景: <template> <input v-model="…

vue实现键盘

vue实现键盘

Vue 实现键盘功能 在Vue中实现键盘功能通常涉及监听键盘事件、处理输入以及渲染虚拟键盘界面。以下是几种常见的实现方式: 监听键盘事件 通过@keydown或@keyup指令监听键盘事件,适用于…

vue实现删除

vue实现删除

Vue 实现删除功能的方法 在 Vue 中实现删除功能通常涉及以下几个步骤: 数据绑定与列表渲染 使用 v-for 指令渲染列表数据,并为每个项绑定唯一标识符(如 id)。例如: <…