【前端】重难点
Dandelion 6/1/2022 interview
# 概述
# 虚拟 DOM 和 Diff 算法
- 如何理解虚拟 DOM?
- 通过 JS 的 Object 对象模拟 DOM 中的节点,然后再通过特定的 render 方法将其渲染成真实的 DOM 节点。
- 真实的 DOM 元素是很复杂的,当频繁地去更新 DOM 节点时,会产生很大的性能开销。
- 虚拟 DOM 就是一个普通的 JavaScript 对象,包含了
tag
、props
、children
三个属性。 - 虚拟 DOM 的优势:
- 通过 Diff 算法,减少 JS 操作真实 DOM 的带来的性能消耗;
- 为函数式的 UI 编程方式打开了大门;
- 抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件以及小程序等。
- Diff 算法的核心原理是什么?
- 比对 JS 原生对象,计算出需要变更的 DOM,然后只对变化的 DOM 进行操作,而不是更新整个视图。
- 通过 JS 层面的计算,返回一个 patch(补丁) 对象,再通过特定的操作解析 patch 对象,完成页面的重新渲染。
- 根据旧 DOM 树和新 DOM 树对应的两个虚拟 DOM,创建出补丁来描述改变的内容,然后利用该补丁来更新 DOM。
- 难点在于判断节点是如何变化的,将比较后的差异节点放到补丁包中。存在以下四种情形:
- 新节点中删除了子节点;
- 文本的变化:判断两个文本是否一样;
- 当两个节点的类型相同时,比较属性;
- 节点直接全被替换。
- DOM-Diff 的具体步骤:
- 用 JS 对象模拟虚拟 DOM,并把该虚拟 DOM 通过 render 方法转成真实 DOM,同时插入页面中;(render)
- 若发生了某个事件后,虚拟 DOM 被修改,则比较此时的虚拟 DOM 和之前的虚拟 DOM 的差异,得到差异对象;(diff)
- 最后,把差异对象应用到真正的 DOM 树上。(patch)
- 比对 JS 原生对象,计算出需要变更的 DOM,然后只对变化的 DOM 进行操作,而不是更新整个视图。
- Virtual DOM VS MVVM
- MVVM 的变化检查是数据层面的,通过 Directive/Binding 对象,观察数据变化并保留对实际 DOM 元素的引用,当有数据变化时进行对应的操作。(如 Vue 和 Angular)
- Virtual DOM 的变化检查无疑是 DOM 结构层面的。(如 React)
- Angular 的脏检查,Vue 的依赖收集,React 的虚拟 DOM。
- 总结:
- 在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
- 主流的框架 + 合理的优化,足以应对绝大部分应用的性能需求。如果是对性能有极致需求的特殊情况,其实应该牺牲一些可维护性采取手动优化。
- 参考