|
|
|
# React 源码的碎片记录
|
|
|
|
- 每一个 Fiber 节点都会链接它的第一个子节点、下一个兄弟节点和父节点,并且在 Fiber 节点中还会保存组件的状态和需要更新的副作用
|
|
|
|
- Reconciler 会从根节点一直向下递到子节点,再从子节点一路向上归到根节点
|
|
|
|
- Fibet 中的 tag 属性保存了组件类型,如 Function Component、Class Component
|
|
|
|
- Fiber 中的 elementType 和 type 属性在大部分时候时相同,但是在 Function Component 使用React.memo 包裹时会有不同
|
|
|
|
- Fiber 中的 type 属性在使用 Function Component 时是函数本身,Class Component 时是 Class,Host Component 时是 DOM 节点的 Tag Name
|
|
|
|
- Fiber 中的 stateNode 属性对于 Host Component 而言,是它的真实 DOM 节点
|
|
|
|
- Fiber 中的 return、child、sibling 属性则对应链接Fiber链表中的父节点、子节点和兄弟节点
|
|
|
|
- Fiber 中的 index 属性代表在多个同级 Fiber 节点中,它们插入的位置索引
|
|
|
|
- Fiber 中带有 effcet 名称的属性代表与副作用相关,Host Component 中的 DOM 的增删改查,Functuon 中的 useEffect、useLayoutEffect
|
|
|
|
- Fiber 中的 lanes 属性和 childLanes 属性与 Fiber 的优先级的调度有关
|
|
|
|
- Fiber 中的 alternate 属性则表示了 Fiber 的工作方式
|
|
|
|
- React 的双缓存:React 有着 current Fiber 树和存在于内存中的 workInProgress Fiber 树
|
|
|
|
- React 的双缓存:每一次 React 的更新都会创建一个 workInProgress Fiber 树,current Fiber 和 workInProgress Fiber 之间使用 alternate 属性链接,方便公用属性,当 workInProgress Fiber 完成渲染,FiberRootNode 的指针就会指向 workInProgress Fiber 树的根节点 RootFiber,这时 workInProgress Fiber 就变成了 current Fiber 树
|
|
|
|
- React 会尽量的复用 Fiber,在创建 workInProgress Fiber 时,如果 current Fiber 中节点的 alternate 属性已经指向一个 Fiber 节点,那么新创建的 workInProgress Fiber 节点就会基于这个 alternate 指向的 Fiber 节点来创建,这种基于已有 Fiber 节点做对比生成新的 workInProgress Fiber 的过程就是 diff 算法,所以首屏渲染和更新渲染最大的区别就在于是否有 diff 算法
|
|
|
|
- 对于首屏渲染来说,只有根节点具有 current Fiber 而子节点不存在
|
|
|
|
- React render 阶段的工作分为归阶段和递阶段,在递阶段执行 beginWork,而在归阶段,执行 completeWork
|
|
|
|
- 如果 render 的递归阶段,如果节点只存在一个文本子节点,那么这个子节点将不会进入 beginWork 递阶段,而是由它父节点直接进入 completeWork 归阶段,这是 React 做的一个优化,而这一个逻辑在 updateHostComponent方法中的 isDirectTextChild 可以看到
|
|
|
|
- Host Components 会进入 updateHostComponent 逻辑,在 React 18 是 updateHostComponent$1
|
|
|
|
- updateHostComponent 方法中的 reconcileChildren 方法会为当前 Fiber 节点创建它的子 Fiber 节点,也就是 Fiber 中的 child 属性
|
|
|
|
- reconcileChildren 方法接受 current 参数,通过判断这个参数是否为 null,分别执行 mountChildFibers 或 reconcileChildFibers 方法
|
|
|
|
- mountChildFibers 和 reconcileChildFibers 都是由 ChildReconciler 方法创建的,只是传入的布尔值会不同,而这个参数表示是否追踪副作用,mountChildFibers 为 false,reconcileChildFibers则相反
|
|
|
|
- 以 reconcileChildFibers 为例,会对 Children 的类型做判断,对判断结果分别做相应操作
|
|
|
|
- completeWork 会对 beginWork 创建好的 Fiber 进行填充,根据 Fiber 类型的不同有不同的处理逻辑,其中有一步就是创建真实 DOM 元素并将之前创建好的 DOM 元素插入
|
|
|
|
- finalizeInitChildren 为创建的 DOM 元素,插入已有的 props,内部也根据 Fiber 节点的 tag 区分不同的处理逻辑,还有对 props 是否合法的校验,甚至根据 props 的属性也做了不同逻辑的处理,最终交由 setValueForProperty 处理
|
|
|
|
- completeWork 中的 appendAllChildren 会将创建好的真实DOM元素插入之前创建的子DOM元素
|
|
|
|
- 对于首屏渲染,只会有一个节点被打上 effectTag,就是根节点,只需要根节点被打上 effectTag 那么就能渲染剩下的全部内容
|
|
|
|
- createWorkInProgress 会创建新的 WorkInProgress Fiber,会根据 current Fiber 的 alternate 属性检查是否已经存在 WorkInProgress Fiber,如果没有会通过 createFiber 创建新的 Fiber 并将 current Fiber 的已有属性进行赋值,最后让 WorkInProgress Fiber 的 alternate 属性进行双向链接
|