1. Diff 算法优化:最长递增子序列 vs 双端对比
核心对比
| 对比维度 | Vue2 双端对比 | Vue3 最长递增子序列 (LIS) |
|---|---|---|
| 时间复杂度 | 最坏 O(n²),平均接近 O(n) | 最优/最坏/平均 O(n log n) |
| 空间复杂度 | O(1)(几个指针) | O(n)(额外数组存索引/前驱) |
为什么 Vue3 更好?
-
Vue2 依赖四个指针移动,在列表大规模乱序时可能频繁移动 DOM,导致性能下降到 O(n²)。
-
Vue3 通过 LIS 算法找出"不需要移动的节点"(即最长递增子序列),其余节点仅作精准插入/移动,保证最少的 DOM 操作次数。
虽然多用了 O(n) 内存,但换来了稳定高效的 O(n log n) 性能,为大型复杂应用提供可靠的上限保障。
2. 静态节点标记与提升
静态节点:内容完全固定、不会改变的节点(如 <div>Hello</div>)。
Vue3 的优化
-
编译器在编译时对静态节点进行静态标记,并提升到渲染函数外部,作为常量创建一次。
-
后续更新时,渲染器看到静态标记,直接跳过对该节点及其子节点的对比,极大减少不必要的 VNode 对比开销。
3. 虚拟 DOM 缓存的实际范围
Vue3 并不是缓存整个项目的所有虚拟 DOM,只在以下有限场景缓存:
缓存场景说明
| 缓存场景 | 说明 | 生命周期 |
|---|---|---|
| 新旧对比临时缓存 | 组件更新时临时生成新树,与旧树对比,对比完成后旧树若无引用即被 GC | 组件级、短暂 |
| 静态提升常量 | 静态节点被提升为常量,一直存在,但数量有限(仅模板中的静态部分) | 持久、有限 |
<KeepAlive> 缓存 | 被 KeepAlive 包裹的组件实例及其虚拟 DOM 树会被保留,以便快速激活。范围仅限显式包裹的组件 | 显式控制 |
总结
Vue3 在性能与内存间做了平衡,不会无脑缓存所有虚拟 DOM。
4. 异步删除操作
定义:组件销毁时,Vue3 不会立即清除,而是标记为"待销毁",在下一个事件循环中批量执行真正的清理和内存回收。
目的
-
给开发者机会在 onBeforeUnmount / onUnmounted 中取消异步任务(定时器、网络请求、事件监听),防止内存泄漏。
-
批量处理多个组件的销毁,减少浏览器重绘/回流压力。
开发者需要做的
-
在对应生命周期钩子中手动释放自己占用的资源(如 clearInterval、removeEventListener、关闭 WebSocket 等)。
-
使用
<KeepAlive>时,清理逻辑放在 deactivated 钩子中。
通过以上四大优化,Vue3 实现了虚拟 DOM 性能的显著提升,为开发者提供了更高效、更可靠的前端开发体验。