(1)before mutation阶段(执行DOM操作前):处理类组件的getSnapShotBeforeUpdate 生命周期函数
- 处理DOM节点渲染/删除后的 autoFocus、blur逻辑;
- 调用getSnapshotBeforeUpdate生命周期钩子;
- 调度useEffect。
(2)mutation阶段(执行DOM操作):将 workInProgress Fiber 树变成 current Fiber 树
- 如果该fiber类型是ClassComponent的话,执行getSnapshotBeforeUpdate生命周期api,将返回的值赋到fiber对象的__reactInternalSnapshotBeforeUpdate上;
- 如果该fiber类型是FunctionComponent的话,执行hooks上的effect相关 API。
代码层面:
- 根据ContentReset effectTag重置文字节点;
- 更新ref;
- 根据effectTag分别处理,其中effectTag包括(Placement | Update | Deletion | Hydrating);
- Placement时:获取父级DOM节点。其中finishedWork为传入的Fiber节点获取Fiber节点的DOM兄弟节点根据DOM兄弟节点是否存在决定调用parentNode.insertBefore或parentNode.appendChild执行DOM插入操作;
- Update时:执行所有useLayoutEffect hook的销毁函数。调用commitWork;6.Deletion时:递归调用Fiber节点及其子孙Fiber节点中fiber.tag为ClassComponent的componentWillUnmount
(opens new window)生命周期钩子,从页面移除Fiber节点对应DOM节点解绑ref调度useEffect的销毁函数。
(3)layout(执行 DOM 操作后):commitHookEffectList()阶段,调用类组件生命周期函数或者函数组件的钩子函数
重置 nextEffect,useEffect是让FunctionComponent产生副作用的hooks,当使用useEffect后,会在fiber上的updateQueue.lastEffect生成effect链,具体请看ReactFiberHooks.js中的pushEffect()
作用:循环FunctionComponent上的effect链,并根据每个effect上的effectTag,执行destroy/create操作(作用类似于componentDidMount/componentWillUnmount)
代码层面:
- 调用componentDidxxx;
- 调用this.setState第二个参数回调函数;
- 调用useLayoutEffect hook的回调函数(与mutation的销毁函数是同步的),调度useEffect的销毁与回调函数(在before
mutation只是先调度加入异步任务,在这里才真正执行),因此useLayoutEffect是同步的,useEffect是异步的;- 获取DOM实例,更新ref5.current Fiber树切换(workInProgress Fiber树在commit阶段完成渲染后会变为current Fiber树)。