React 执行架构流程详细----递阶段 mount 时流程(二)
引言
在上一篇中了解到:
-
render 阶段开始于 renderRootSync,commit 阶段开始于 commitRoot
-
render 阶段使用遍历来实现了可中断的递归,其中递归可以分为 递阶段和归阶段
-
递阶段就是执行的 beginWork,归阶段就是执行的 completeWork
-
render 阶段不会执行具体的dom操作,具体的dom操作是在commit 阶段执行,render阶段需要做的就是为需要执行的dom操作的 fiber 节点打上标记,若节点需要插入在页面中,就打上 Placement 标记;若节点需要删除,就打上 deletion的标记
四个阶段
在阐述双缓存机制时了解到,在 mount时,不存在对应的 currentFiber 树,而在 update 时,存在一棵 currentFiber 树,所以在 mount 和 update 时,beginWork 和 completeWork 的工作会有一些不同,所以就分为以下四种情况来阐述:
递阶段 mount 时流程
也就是 mount 时 beginwork 的过程
比如页面是以下结构:
原理就是 DFS ,执行的过程是:
render 阶段完成之后,然后就进入了 commit 阶段
PS:react 对于 只有唯一文本子节点的节点 会做一个优化处理,比如 上面的 code 标签节点,这种文本节点不会生成自己的 fiber 节点,所以就没有该文本节点的 beginwork 和 completework的过程
beginWork 函数解析
举个🌰:
比如 以 div 标签的 beginWork 和 completeWork 来举例子:
- beginWork 首先会根据当前 workInProgress.tag 的类型来进入不同的 case
由于 div 属于 host component ,所以就进入 updateHostComponent 的逻辑
- 在 updateHostComponent 中,首先会赋值一些变量,注意 isDirectTextChild 变量就是判断 该节点是否是子节点只含有文本节点,若是这种情况的话,会有优化
- 之后会进入 reconcileChildren 函数:
- reconcileChildFibers 会判断当前 child 的类型,进入不同的处理逻辑,最后通过 react element 的属性等进而创建不同的 fiber 节点
- reconcileChildFibers 和 mountChildFibers 函数的区别
进入 mountChildFibers 函数中创建的 fiber 节点,他是不会被标记的
(详情请看下一篇)
从这可以看出 reconcileChildFibers 和 mountChildFibers 函数的区别:
- 具体看 ChildReconciler 函数:这个 boolean 值就是 是否追踪副作用,从下面的来看,在 deleteChild 中,如果不支持副作用,则直接 return;如果要追踪副作用,会把 effectTag 打上 deletion 的标记;
placeChild 类似,placeChild 代表需要将当前fiber节点对应的 dom 节点插入到页面中,如果不需要追踪副作用,就直接 return;若需要追踪副作用,会为这个fiber节点的 effectTag 打上 Placement 的标记
- 看具体的副作用的定义
使用二进制来定义副作用的原因是:
举个🌰:
若一个 fiber 节点(对应一个dom节点),首先需要插入到页面中,之后需要更新它的属性,所以就会同时存在 placement 和 update 两种 effectTag,即一个节点先 placement,再 update(即进行多次副作用的处理),在这种情况下,使用二进制非常方便就能实现这些功能,通过 按位或,按位与等操作来实现
使用按位或、按位与的操作易于实现存在多种 effectTag 标记
总结
执行栈:
当某一个 fiber 节点进入 beginWork 时,他最终的目的是为了创建当前fiber 节点的一个子fiber节点:
- 首先会判断当前fiber节点的类型,进入不同的 update 的逻辑;
- 在 update 的逻辑中,他会判断当前的workInProgress fiber 中是否存在对应的 current fiber,来决定是否标记 effectTag
- 接着,会借助 reconciler 的逻辑,在 reconciler 中,会判断当前 fiber 节点的 children是什么类型,来执行不同的创建操作(比如是div节点,属于 hostComponent,是一个单一的 ReactElement 的type,所以会进入 reconcileSingleElement 函数)
- 最终会创建一个 子fiber 节点
参考资料:
React 项目源码
技术揭秘
React 版本是17