sufuwang / demo

My study note about technology
0 stars 0 forks source link

React Diff Algorithm #12

Open sufuwang opened 1 year ago

sufuwang commented 1 year ago

reconcile 流程

《React 设计原理》对 reconcile 流程的描述如下

reconcile 流程的本质,是对比 current fiberNode 与 JSX 对象,生成 wip fiberNode。除 React 外,其他使用虚拟 DOM 技术的前端框架都有类似流程(比如 Vue 中的 patch 操作),这一流程的核心算法被称为 Diff 算法

这里的 current fiberNode 就是 Fiber 架构中的前缓冲区,生成的 wip fiberNode 是后缓冲区

sufuwang commented 1 year ago

三个限制

这三个限制为了降低 Diff 算法的复杂度

  1. 只对同级元素进行 Diff。如果一个 DOM 元素在前后两次更新中跨越了层级,那么 React 不会尝试复用他
  2. 两个不同类型的元素会产生不同的树。如果元素由 Div 变为 P,React 会销毁 Div 及其子孙元素,并新建 P 及其子孙元素
  3. 开发者可以通过 key 来暗示哪些子元素在不同的渲染下能够保持稳定

React 默认对比同层级 DOM 元素,如果 DOM 元素的顺序改变,则需要添加 key 来复用 DOM ,来突破限制二的约束

sufuwang commented 1 year ago

Diff 算法

单节点 Diff

reconcile 流程的本质,是对比 current fiberNode 与 JSX 对象,生成 wip fiberNode

单节点对比时,步骤如下

  1. 判断是否存在 current fiberNode ,若不存在,则不需要对比,直接生成对应的 wip fiberNode
  2. 判断 current fiberNode 是否可以复用,key 和 DOM 元素 type 均一致的情况下才可以复用 a. 若不能复用,则标记 current fiberNode 需要被删除,然后生成新的 wip fiberNode b. 若可以复用,复用 current fiberNode 生成新的 wip fiberNode

多节点 Diff

Diff 算法会遍历两次 fiberNode,第一轮遍历尝试复用节点,第二轮遍历处理剩下的节点,包括新增、删除、移动 DOM 元素

假设一个场景,现在是需要对比同层级的 \

  • 元素,current fiberNode 以链表的数据结构存储,而 JSX 对象则是以数组的数据结构存储。因为无法使用双指针,所以无法借鉴 Vue 的双端/快速 Diff 算法。React 判断 DOM 元素是否需要移位的逻辑,与 Vue 的简单 Diff 算法的逻辑一致,维护一个最大索引,若 current fiberNode 的索引小于这个最大索引,则需要移位。具体参考 #10 Vue 简单 Diff 算法