【前端】重难点

6/1/2022 interview

# 概述

# 虚拟 DOM 和 Diff 算法

  • 如何理解虚拟 DOM?
    • 通过 JS 的 Object 对象模拟 DOM 中的节点,然后再通过特定的 render 方法将其渲染成真实的 DOM 节点。
    • 真实的 DOM 元素是很复杂的,当频繁地去更新 DOM 节点时,会产生很大的性能开销。
    • 虚拟 DOM 就是一个普通的 JavaScript 对象,包含了 tagpropschildren 三个属性。
    • 虚拟 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)
  • Virtual DOM VS MVVM
    • MVVM 的变化检查是数据层面的,通过 Directive/Binding 对象,观察数据变化并保留对实际 DOM 元素的引用,当有数据变化时进行对应的操作。(如 Vue 和 Angular)
    • Virtual DOM 的变化检查无疑是 DOM 结构层面的。(如 React)
    • Angular 的脏检查,Vue 的依赖收集,React 的虚拟 DOM。
  • 总结:
    • 在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
    • 主流的框架 + 合理的优化,足以应对绝大部分应用的性能需求。如果是对性能有极致需求的特殊情况,其实应该牺牲一些可维护性采取手动优化。
  • 参考
Last Updated: 10/8/2022, 2:29:52 PM