commitRoot是commit的起点,fiberRootNode会作为传参commitRoot(root)
做了什么操作
- 执行副作用: 在rootFiber.firstEffect上保存了一条需要执行副作用的fiber节点的单向链表effectList,这些节点的updateQueue中保存了变化的props(props是一个数组)这些副作用都会在commit阶段执行。
- 一些生命周期函数、hook、需要在commit阶段执行。
commit工作流程主要分为三部分
before mutation DOM操作前
主要是做一些变量赋值、状态重置工作。
- 将effectList赋值给firstEffect,由于每个fiber的effectList只包含他的子孙节点,所以根节点如果有effectTag则不会被包含进来,所以将有effectTag的根结点插到effectList的尾部,这样保证有effect的fiber在effectList中,遍历effectList。
- 调用commitBeforeMutationEffects,
函数中处理了
a. dom渲染后的autoFocus、blur逻辑
b. 调用getSnapShotBeforeUpdate生命周期
c. 异步调度useEffect(与优先级有关,防止同步执行阻塞浏览器渲染,useLayoutEffect是同步的)
* 异步调度useEffect分为三部:
1. before mutation阶段 在scheduleCallback中调度flushPassiveEffects。
2. layout阶段之后将effectList赋值给rootWithPendingPassiveEffects。
3. scheduleCallback触发flushPassiveEffects,flushPassiveEffects内部遍历rootWithPendingPassiveEffects
mutation DOM操作
遍历effectList,执行commitMutationEffects,commitMutationEffects主要是对每个fiber进行视图的操作,包括:文字节点处理、ref处理、根据effectTag对组件增删改查。
ps1:如果是dom元素的更新操作会相应处理style、dangerouslySetInnerHTML、children等属性
ps2: 更新操作会触发useLayoutEffect的销毁函数
ps3: 如果删除组件操作,会调用对应的useEffect销毁函数或componentWillUnMount
layout DOM渲染完成后
主要完成了 useEffect相关处理,性能追踪,一些生命周期钩子(componentDidxxx)、hook(useLayoutEffect\useEffect),赋值ref等
遍历effectList,执行commitLayoutEffects。
function commitLayoutEffects(root: FiberRoot, committedLanes: Lanes) {
while (nextEffect !== null) {
const effectTag = nextEffect.effectTag;
// 调用生命周期钩子和hook
if (effectTag & (Update | Callback)) {
const current = nextEffect.alternate;
commitLayoutEffectOnFiber(root, current, nextEffect, committedLanes);
}
// 赋值ref
if (effectTag & Ref) {
commitAttachRef(nextEffect);
}
nextEffect = nextEffect.nextEffect;
}
}
commitLayoutEffectOnFiber
- 根据current===null判断是mount还是update,调用componentDidMount或者componentDidUpdate。
- 触发setState的回调函数
- 调用useLayout的回调(同步的),调度useEffect的销毁与回调(异步的)。
因为双缓存机制,需要切换fiber树,这个操作在mutation前,layout后执行
root.current=finishedWork
因为componentWillUnmount会在mutation阶段执行,current Fiber树指向更新前的fiber树,在生命周期钩子内获取的dom是更新前的。
componentDidMount和componentDidUpdate会在layout阶段执行,current Fiber树指向更新后的fiber树,生命周期内获取到的DOM是更新后的。
网友评论