|
|
|
commitMutationEffects 对应 commit 中的 mutation 阶段,这个方法内部是一个 while 循环,遍历 effectList 链表,遍历到的每一个 Fiber 节点首先会判断是否存在 ConentReset 标记,这个标记表示 Fiber 是否需要重置文本节点
|
|
|
|
|
|
|
|
### commitResetTextContent
|
|
|
|
|
|
|
|
然后会判断是否存在 Ref 标记
|
|
|
|
|
|
|
|
### commitDetachRef
|
|
|
|
|
|
|
|
然后进入 mutation 阶段最重要的逻辑:判断 Fiber 阶段是否存在以下 effectTag
|
|
|
|
1. Placement 插入DOM
|
|
|
|
2. Update 更新属性
|
|
|
|
3. Deletion 删除 DOM 节点
|
|
|
|
4. Hydrating SSR 相关
|
|
|
|
|
|
|
|
然后根据 effectTag 不同进入不同的处理逻辑
|
|
|
|
|
|
|
|
## Placement
|
|
|
|
|
|
|
|
commitPlacement
|
|
|
|
如果当前环境不支持 mutation 会直接返回,ReactDOM 下是支持的
|
|
|
|
首先会根据当前的 Fiber 节点,找到其最近的 Host 类型的父 Fiber 节点,Host 类型包括 HostComponent、HostRoot、HostPortal 和 FundamentalComponent,这几种类型有一个共同点:它们都有对应的 DOM 节点
|
|
|
|
找到之后先进行各自的前置处理逻辑
|
|
|
|
|
|
|
|
### getHostParetFiber
|
|
|
|
|
|
|
|
一直递归向上查找,直到找到 HostComponent 为止
|
|
|
|
|
|
|
|
如果父 Fiber 节点上存在 ConentReset 标记,就要先执行 resetTextConent 函数,然后会找到当前 Fiber 节点的 Host 类型的兄弟节点
|
|
|
|
|
|
|
|
### getHostSibling
|
|
|
|
该方法内部有着一个嵌套循环,因为兄弟 HostComponents 的查找可能是跨层级的
|
|
|
|
|
|
|
|
为什么要找到最近的兄弟节点 HostComponent?
|
|
|
|
- 因为 DOM 的插入有两种方法,第一种是 insertBefore 方法,第二种是 appendChild
|
|
|
|
- 使用 insertBefore 时需要找到兄弟节点
|
|
|
|
- 使用 appendChild 时需要找到父节点
|
|
|
|
|
|
|
|
### insertInContainerBefor
|
|
|
|
|
|
|
|
内部实际上还是使用了 insertBefore 方法
|
|
|
|
|
|
|
|
### appendChildToContainer
|
|
|
|
内部实际上还是使用了 appendChild 方法
|
|
|
|
|
|
|
|
## PlacementAndUpdate
|
|
|
|
|
|
|
|
先调用 commitPlacement 方法,接着调用 commitWork
|
|
|
|
|
|
|
|
### commitWork
|
|
|
|
|
|
|
|
与 Function 有关的类型,会调用 commitHookEffectListUnmount
|
|
|
|
|
|
|
|
### commitHookEffectListUnmount
|
|
|
|
|
|
|
|
会调用 useLayoutEffect 的销毁函数,内部会遍历 EffectList,如果包含传入的 tag,当前是 HookLayout,也就是内部存在 useLayoutEffect 的函数组件,那么会执行它们 useLayoutEffect 的回调函数,也就是 useLayoutEffect 的 return
|
|
|
|
|
|
|
|
在执行任意 useEffectLayout 的回调函数之前,会先执行所有 useEffectLayout 的销毁函数
|
|
|
|
|
|
|
|
HostComponent 组件,会调用 commitUpdate 方法
|
|
|
|
|
|
|
|
### commitUpdate
|
|
|
|
且接收的 updatePayload 参数就是当前 Fiber 组件的 updateQueue 属性
|
|
|
|
内部最终会调用 updateProperties 函数来更新 DOM 的 props
|
|
|
|
|
|
|
|
|
|
|
|
## Deletion
|
|
|
|
|
|
|
|
会执行 commitDeletion 函数
|
|
|
|
|
|
|
|
### commitDeletion
|
|
|
|
如果支持 mutation,那么会调用 unmountHostComponents
|
|
|
|
|
|
|
|
### unmountHostComponents
|
|
|
|
|
|
|
|
### commitNestedUnmount
|
|
|
|
递归删除 Fiber 子节点
|
|
|
|
|
|
|
|
### commitUnmount
|
|
|
|
|
|
|
|
对于 FunctionComponent 类型的组件,需要执行 enqueuePendingPassiveHookEffectUnmount 函数,也就是注册需要被执行的 useEffect 回调函数
|
|
|
|
|
|
|
|
对于 ClassComponents 类型的组件,会执行它的 componentWillUnmount 生命周期函数
|
|
|
|
|
|
|
|
对于 HostComponents 类型的组件,会解绑它的 ref 属性
|