第一章 JSX(React18源码解析一)
第二章 实现Virtual DOM(React18源码解析二)
第三章 根节点关联根Fiber(React18源码解析三)
第四章 初始化UpdateQueue、添加update(React18源码解析四)
第五章 实现时间切片函数和拷贝Fiber(React18源码解析五)
第六章 构建FiberTree(React18源码解析六)
第七章 commit(React18源码解析七)
第八章 React中的事件(React18源码解析八)
第九章 useReducer、useState(React18源码解析九)
第十章 React的dom diff(React18源码解析十)
第十一章 React的Effect(React18源码解析十一)
第十二章 React的同步、并发渲染(React18源码解析十二)
第十三章 React高优打断低优、饥饿问题(React18源码解析十三)
原则
同级比较,key、type相同复用
经历三次循环
1.遍历old children、new children
a.key、type相同复用
b.key相同type不同,删除old child添加new child
c.key不同结束此循环直接进入(3)移动循环
2.若(1)循环结束
a.old children遍历结束,new children还未结束,把剩下的都添加上去
b.new children遍历结束,old children还未结束,把剩下的都删除
3.移动
a.把剩下的oldFiber放入map existingChildren中
b.声明变量lastPlacedIndex,标识不需要移动节点在oldChildrens中的下标
c.如能在map中找到key、type相同的节点,及复用此节点,在map中删除oldFiber
d.如复用节点,判断节点在old childrens中的index是否大与lastPlacedIndex,大于则不需要移动,用index更新lastPlacedIndex
e.若小与,则需要把old childrens中的节点移动到lastPlacedIndex处
f.把map剩下的节点标记为删除
说明
DIFF的过程中会出现更新、插入、删除、插入更新等四种操作
1.更新:
在beginWork阶段根据old fiber创建new fiber,在completeWork阶段根据fiber.memoizedProps和element.props得到updatePayload,添加到newFiber的updateQueue上,并把newFiber.flags标识为Update,在commitRoot阶段根据副作用标识更新dom
2.插入:
在beginWork阶段根据待插入dom对应的虚拟dom创建fiber,fiber.flags标识为Placement,在completeWork阶段创建真实dom,在commitRoot阶段根据副作用标识插入dom
3.删除:
把待删除的fiber添加到parent fiber.deletions上,parent fiber.flags标识为ChildDeletion,在commitRoot阶段根据副作用遍历parent fiber.deletions删除废弃节点
4.插入更新:
插入更新就是移动,底层利用了dom映射的原理,在beginWork阶段根据oldFiber创建newFiber,在completeWork阶段根据fiber.memoizedProps和element.props计算出updatePayload,添加到newFiber的updateQueue上,并把newFiber.flags标识为MutationMask(Placement | Update),在commitRoot阶段根据副作用标识移动更新dom
备注:
本文只贴出实现原理,观者可对照源码学习,源码地址:/packages/react-reconciler/src/ReactChildFiber.js