看卡颂文章的学习笔记,此处链接| iamkasong
每个 Fiber Node 对应 React Element
主要分三类
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
// 作为静态数据结构的属性
this.tag = tag;
this.key = key;
this.elementType = null;
this.type = null;
this.stateNode = null;
// 用于连接其他Fiber节点形成Fiber树
this.return = null;
this.child = null;
this.sibling = null;
this.index = 0;
this.ref = null;
// 作为动态的工作单元的属性
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
this.dependencies = null;
this.mode = mode;
this.effectTag = NoEffect;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
// 调度优先级相关
this.lanes = NoLanes;
this.childLanes = NoLanes;
// 指向该fiber在另一次更新时对应的fiber
this.alternate = null;
}
在内存中绘制当前帧动画,绘制完毕后直接用当前帧替换上一帧画面,避免白屏闪烁的情况出现
React 使用“双缓存”来完成 Fiber 树的构建与替换(对应着 DOM 树的创建与更新)。
同时两棵树的 Fiber 节点会通过
alternate属性连接起来。
该阶段异步
从rootFiber开始深度优先遍历,创建传入的FiberNode的子节点,当遍历到叶节点。
fiber.tag渲染对应FiberNode(FunctionComponent、ClassComponent、HostComponent)。props和fiber.type不变可以理解为递归的”递”阶段
effectTag: render 阶段后通知
Renderer需要执行的 DOM 操作(PlacementAndUpdate、Deletion)
处理propsupdate
当前阶段下已存在 DOM 节点,主要是处理props
处理HostComponent的时候,处理好的props会赋值到workInProgress.updateQueue并在commit阶段进行渲染
effectList: 为了提高性能,会在此阶段生成 effectList(单向链表)作为 DOM 操作的依据
该阶段同步
里面又分三个阶段:
这里每个阶段本质都是遍历
effectList
before mutation阶段
执行 DOM 操作前,遍历 effectList 并调用commitBeforeMutationEffects函数。
- commitBeforeMutationEffects
- 处理 DOM 渲染/删除后的
autoFocus、blur逻辑- 调用
getSnapshotBeforeUpdate生命周期函数
(commit 阶段同步执行,不会重复执行)- 调度
useEffect// TODO 这里需要补充如何调度有
useEffect和useLayoutEffect的 Fiber 节点也会被赋值effectTagmutation阶段
执行 DOM 操作,遍历 effectList 并调用commitMutationEffects函数。
- commitMutationEffects
- 重置文本节点(节点的文字内容设置为空字符串)
- 更新ref
- 根据effectTag执行对应的DOM操作
- Placement
- 获取父级DOM节点
- 获取Fiber节点的DOM兄弟节点
- 根据步骤二结果调用
parent.insertBefore或parent.appendChild- Update
- FunctionComponent mutation
遍历effectList,执行所有useLayoutEffect的销毁函数- HostComponent mutation
- Deletion
- commitDeletion
- 递归Fiber节点及其子孙Fiber节点中的
fiber.tag为ClassComponent的componentWillUnmount的生命周期函数,从页面中移除对应DOM节点- 解绑
ref- 调度
useEffect的销毁函数layout阶段
- commitLayoutEffects
- commitLayoutEffectOnFiber
- ClassComponent
根据mount或update阶段的effectTag执行对应的生命周期函数(componentDidMount或componentDidUpdate)- FunctionComponent
- 调用
useLayoutEffect的回调函数- 调度
useEffectTODO 这里不确定- commitAttachRef 执行 DOM 操作后,