这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战
diff 策略
算法复杂度O(n)
- 同级比较,Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。
- 拥有不同类型的两个组件将会生成不同的树形结构。 例如:div->p, CompA->CompB
- 开发者可以通过 key prop 来暗示哪些子元素在不同的渲染下能保持稳定;
diff过程
比对两个虚拟dom时会有三种操作:删除、替换和更新
vnode是现在的虚拟dom,newVnode是新虚拟dom。
- 删除:newVnode不存在时
- 替换:vnode和newVnode类型不同或key不同时
- 更新:有相同类型和key但vnode和newVnode不同时
在实践中也证明这三个前提策略是合理且准确的,它保证了整体界面构建的性能。
Fiber diff策略
rootFiber开始向下深度优先遍历。为遍历到的每个Fiber节点调用beginWork方法 (opens new window)。方法
该方法会根据传入的Fiber节点创建子Fiber节点,并将这两个Fiber节点连接起来。
当遍历到叶子节点(即没有子组件的组件)时就会调用completeWork (opens new window)处理Fiber节点。
当某个Fiber节点执行完completeWork,如果其存在兄弟Fiber节点(即fiber.sibling !== null),会进入其兄弟Fiber调用beginWork方法
如果不存在兄弟Fiber,会进入父级Fiber会调用completeWork方法
用以下例子讲清楚Fiber 层级对比策略
graph TD
A --> B -->D
B --> E
A --> C
A --> H
以上为构建的dom 树,
- 会从根节点A向下深度优先遍历,因为A.child(dom 节点里的第一个子节点) = B,对B做 completeWork
- B.child = D , 对D做 completeWork
- 因为D不存在子节点,此时要找B的兄弟节点 B.sbling -> C, 对C做 completeWork
- 因为C不存在子节点,此时找C的兄弟节点C.sbling -> H, 对H做 completeWork
- 因为H 既不存在子节点,也不存在兄弟节点,会找其父节点,此时找到C.return -> A