当前位置: 首页 > news >正文

北京品牌网站建设阿里巴巴logo图片

北京品牌网站建设,阿里巴巴logo图片,制作灯笼的手工做法简单,奉贤网站建设专家更新流程的目的#xff1a; 生成wip fiberNode树标记副作用flags 更新流程的步骤#xff1a; 递#xff1a;beginWork归#xff1a;completeWork 在 上一节 #xff0c;我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中#xff…更新流程的目的 生成wip fiberNode树标记副作用flags 更新流程的步骤 递beginWork归completeWork 在 上一节 我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中beginWork 和 completeWork 两个方法起到了关键作用。beginWork 负责构建表示更新的 Fiber 树而 completeWork 则将这个 Fiber 树映射到实际的 DOM 结构上。接下来我们将深入实现这两个方法。 开发环境打印日志 首先在开发环境下增加 DEV 标识以便在开发环境中方便地打印日志 pnpm i -D -w rollup/plugin-replace安装完成后在 scripts/rollup/utils.js 中引入 // scripts/rollup/utils.js // ... import replace from rollup/plugin-replace ; // ... export function getBaseRollupPlugins ( { alias { __DEV__: true }, typescript {} } {} ) { return [ replace (alias), cjs (), ts (typescript)]; } 这样我们就可以在开发环境中打印日志了。 实现 beginWork 对于如下结构的reactElement: AB/ A/当进入A的beginWork时通过对比B的current fiberNode 与B的reactElement生成对应wip fiberNode beginWork 函数在向下遍历阶段执行根据 Fiber 节点的类型HostRoot、HostComponent、HostText分发任务给不同的处理函数处理具体节点类型的更新逻辑 export const beginWork (wip: FiberNode) {switch (wip.tag) {case HostRoot:return updateHostRoot(wip)case HostComponent:return updateHostComponent(wip)case HostText:return nulldefault:if (__DEV__) {console.warn(beginWork为实现的类型, wip)}break} }HostRoot /** 处理根节点的更新包括协调处理根节点的属性 以及子节点的更新逻辑 */ function updateHostRoot(wip: FiberNode) {const baseState wip.memoizedStateconst updateQueue wip.updateQueue as UpdateQueueElementconst pending updateQueue.shared.pendingupdateQueue.shared.pending null // 清空更新链表// 1.计算状态的最新值const { memoizedState } processUpdateQueue(baseState, pending) // 计算待更新状态的最新值wip.memoizedState memoizedState // 更新协调后的状态最新值// 2. 创造子fiberNodeconst nextChildren wip.memoizedState // 获取 children 属性reconcileChildren(wip, nextChildren) // 处理根节点的子节点可能会递归调用其他协调函数// 返回经过协调后的新的子节点链表return wip.child }表示根节点即应用的最顶层节点调用 updateHostRoot 函数处理根节点的更新包括协调处理根节点的属性以及子节点的更新逻辑调用 reconcileChildren 函数处理根节点的子节点可能会递归调用其他协调函数返回 workInProgress.child 表示经过协调后的新的子节点链表 HostComponent function updateHostComponent(wip: FiberNode) {const nextProps wip.pendingProps// 创造子fiberNodeconst nextChildren nextProps.children // 获取Dom的children属性reconcileChildren(wip, nextChildren) // 处理原生 DOM 元素的子节点更新可能会递归调用其他协调函数return wip.child }表示原生 DOM 元素节点例如 div、span 等调用 updateHostComponent 函数处理原生 DOM 元素节点的更新负责协调处理属性和子节点的更新逻辑调用 reconcileChildren 函数处理原生 DOM 元素的子节点更新返回 workInProgress.child 表示经过协调后的新的子节点链表 HostText 表示文本节点即 DOM 中的文本内容例如 p123/p 中的 123调用 updateHostText 函数协调处理文本节点的内容更新返回 null 表示已经是叶子节点没有子节点了 其中 reconcileChildren 函数的作用是通过对比子节点的 current FiberNode 与 子节点的 ReactElement来生成子节点对应的 workInProgress FiberNode。current 是与视图中真实 UI 对应的 Fiber 树workInProgress 是触发更新后正在 Reconciler 中计算的 Fiber 树。 function reconcileChildren(wip: FiberNode, children?: ReactElementType) {const current wip.alternateif (current ! null) {// updatewip.child reconcileChildFibers(wip, current?.child, children)} else {// mountwip.child mountChildFibers(wip, null, children)} }reconcileChildren 函数中调用了 reconcileChildFibers 和 mountChildFibers 两个函数它们分别负责处理更新阶段和首次渲染阶段的子节点协调。 reconcileChildFibers: reconcileChildFibers 函数作用于组件的更新阶段即当组件已经存在于 DOM 中需要进行更新时。主要任务是协调处理当前组件实例的子节点对比之前的子节点current和新的子节点workInProgress之间的变化。根据子节点的类型和 key 进行对比决定是复用、更新、插入还是删除子节点最终形成新的子节点链表。 mountChildFibers: mountChildFibers 函数作用于组件的首次渲染阶段即当组件第一次被渲染到 DOM 中时。主要任务是协调处理首次渲染时组件实例的子节点。但此时是首次渲染没有之前的子节点所以主要是创建新的子节点链表。 // packages/react-reconciler/src/childFiber.ts /** 实现生成子节点fiber 以及标记Flags的过程 */import { ReactElementType } from shared/ReactTypes import { FiberNode, createFiberFromElement } from ./fiber import { REACT_ELEMENT_TYPE } from shared/ReactSymbols import { HostText } from ./workTags import { Placement } from ./fiberFlagsfunction ChildrenReconciler(shouldTrackEffects: boolean) {/** 处理单个 Element 节点的情况对比 currentFiber 与 ReactElement生成 workInProgress FiberNode */function reconcileSingleElement(returnFiber: FiberNode,currentFiber: FiberNode | null,element: ReactElementType) {// 根据element创建fiberconst fiber createFiberFromElement(element)fiber.return returnFiberreturn fiber}/** 处理文本节点的情况对比 currentFiber 与 ReactElement生成 workInProgress FiberNode */function reconcileSingleTextNode(returnFiber: FiberNode,currentFiber: FiberNode | null,content: string | number) {const fiber new FiberNode(HostText, { content }, null)fiber.return returnFiberreturn fiber}/** 为 Fiber 节点添加更新 flags */function placeSingleChild(fiber: FiberNode) {// 优化策略首屏渲染且追踪副作用时才添加更新 flagsif (shouldTrackEffects fiber.alternate null) {fiber.flags | Placement}return fiber}// 闭包根据 shouldTrackSideEffects 返回不同 reconcileChildFibers 的实现return function reconcileChildFibers(returnFiber: FiberNode,currentFiber: FiberNode | null,newChild?: ReactElementType) {// 判断当前fiber的类型// 1. 单个 Element 节点if (typeof newChild object newChild ! null) {switch (newChild.$$typeof) {case REACT_ELEMENT_TYPE:return placeSingleChild(reconcileSingleElement(returnFiber, currentFiber, newChild))default:if (__DEV__) {console.warn(未实现的reconcile类型, newChild)}break}}// TODO 2. 多个 Element 节点 ul li*3// 3. HostText 节点if (typeof newChild string || typeof newChild number) {return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFiber, newChild))}// 4. 其他if (__DEV__) {console.warn(未实现的reconcile类型, newChild)}return null} }/** 处理更新阶段的子节点协调组件的更新阶段中追踪副作用*/ export const reconcileChildFibers ChildrenReconciler(true) /** 处理首次渲染阶段的子节点协调首屏渲染阶段中不追踪副作用只对根节点执行一次 DOM 插入操作*/ export const mountChildFibers ChildrenReconciler(false)// packages/react-reconciler/src/fiber.ts // .../** 根据element创建fiber并返回 */ export function createFiberFromElement(element: ReactElementType) {const { type, key, props } elementlet fiberTag: WorkTag FunctionComponentif (typeof type string) {// div/ type: divfiberTag HostComponent} else if (typeof type ! function __DEV__) {console.warn(未定义的type类型, element)}// 创建 fiber 节点const fiber new FiberNode(fiberTag, props, key)fiber.type typereturn fiber }beginWork性能优化策略 考虑如下结构的reacetElement: divp练习时长/pspan两年半/span /div理论上mount流程完毕后包含的flags: 两年半 PlacementSpan Placement练习时长 PlacementP PlacementDiv Placement 相比执行5次Placement我们可以构建好离屏DOM树后对div执行1次Placement操作 实现 completeWork 需要解决的问题 对于 Host 类型 fiberNode: 构建离屏Dom树标记 Update flag (TODO) completeWork 函数在向上遍历阶段执行根据 Fiber 节点的类型HostRoot、HostComponent、HostText 等构建 DOM 节点收集更新 flags并根据更新 flags 执行不同的 DOM 操作 HostComponent: 表示原生 DOM 元素节点构建 DOM 节点并调用 appendAllChildren 函数将 DOM 插入到 DOM 树中收集更新 flags并根据更新 flags 执行不同的 DOM 操作例如插入新节点、更新节点属性、删除节点等 HostText: 表示文本节点构建 DOM 节点并将 DOM 插入到 DOM 树中收集更新 flags根据 flags 的值更新文本节点的内容 HostRoot: 表示根节点会执行一些与根节点相关的最终操作例如处理根节点的属性确保整个应用更新完毕 export const completeWork (wip: FiberNode) {const newProps wip.pendingPropsconst current wip.alternateswitch (wip.tag) {case HostComponent:if (current ! null wip.stateNode) {//update} else {// mount 构建离屏的 Dom 树// 1. 构建 Domconst instance createInstance(wip.type, newProps)// 2. 将Dom插入到Dom树中appendAllChildren(instance, wip)wip.stateNode instance}bubbleProperties(wip)return nullcase HostText:if (current ! null wip.stateNode) {//update} else {// mount// 1. 构建 Domconst instance createTextInstance(newProps.content)wip.stateNode instance}bubbleProperties(wip)return nullcase HostRoot:bubbleProperties(wip)return nulldefault:if (__DEV__) {console.warn(completeWork未实现的类型, wip)}break} }其中appendAllChildren 函数负责递归地将组件的子节点添加到指定的 parent 中它通过深度优先遍历 workInProgress 的子节点链表处理每个子节点的类型。先处理当前节点的所有子节点再处理兄弟节点。 如果它是原生 DOM 元素节点或文本节点则将其添加到父节点中如果是其他类型的组件节点并且有子节点则递归处理其子节点。 // packages/react-reconciler/src/completeWork.ts // ... function appendAllChildren(parent: FiberNode, wip: FiberNode) {let node wip.child// 递归插入while (node ! null) {if (node?.tag HostComponent || node?.tag HostText) {appendInitialChild(parent, node?.stateNode)} else if (node.child ! null) {node.child.return nodenode node.childcontinue}// 终止条件if (node wip) {return}// 子节点结束开始处理兄弟节点while (node.sibling null) {// 1.当前节点无兄弟节点if (node.return null || node.return wip) {return}node node?.return}// 2.当前节点有兄弟节点node.sibling.return node.returnnode node.sibling} }completeWork 性能优化策略 flags分布在不同fiberNode中如何快速他们 利用completeWork向上遍历(归)的流程将子fiberNode的flags冒泡到父fiberNode 创建 bubbleProperties 函负责在 completeWork 函数向上遍历的过程中通过向上冒泡子节点的 flags将所有更新 flags 收集到根节点。主要包含以下步骤 从当前需要冒泡属性的 Fiber 节点开始检查是否有需要冒泡的属性。如果当前节点有需要冒泡的属性将这些属性冒泡到父节点的 subtreeFlags 或其他适当的属性中。递归调用 bubbleProperties 函数处理父节点将属性继续冒泡到更上层的祖先节点直至达到根节点。 // packages/react-reconciler/src/completeWork.ts // .../** 收集更新 flags将子 FiberNode 的 flags 冒泡到父 FiberNode 上 */ function bubbleProperties(wip: FiberNode) {let subtreeFlags NoFlagslet child wip.childwhile (child ! null) {subtreeFlags | child.subtreeFlagssubtreeFlags | child.flagschild.return wipchild child.sibling}wip.subtreeFlags | subtreeFlags }位运算简介 flags 是 React 中很重要的一环具体作用是通过二进制在每个 Fiber 节点保存其本身与子节点的 flags。在保存与处理 flags 时使用了一些二进制运算符我们来复习一下 1. | 运算 | 运算的两个位都为 0 时结果才为 0 1 | 1 11 | 0 10 | 0 0 React 利用了 | 运算符的特性来存储 flags如 ts 复制代码 const NoFlags /* */ 0b0000000;const PerformedWork /* */ 0b0000001;const Placement /* */ 0b0000010;const Update /* */ 0b0000100;const ChildDeletion /* */ 0b0001000;const flags Placement | Update; //此时 flags 0b00001102. 运算 运算的两个位都为 1 时结果才为 1 1 1 11 0 00 0 0 React 中会用一个 flags 某一个 flag来判断 flags 中是否包含某一个 flag如 ts 复制代码 const flags Placement | Update; //此时 flags 0b0000110Boolean(flags Placement); // true, 说明 flags 中包含 PlacementBoolean(flags ChildDeletion); // false, 说明 flags 中不包含 ChildDeletion3. ~ 运算 运算符会把每一位取反0 变 11 变 0 ~1 0~0 1 在 React 中~ 运算符同样是常用操作如 ts 复制代码 let flags Placement | Update; //此时 flags 0b0000110flags ~Placement; //此时 flags 0b0000100通过 ~ 运算符与 运算符的结合从 flags 中删除了 Placement 这个 flag。 至此我们就实现了 React 协调阶段中的 beginWork 和 completeWork 函数生成了一棵表示更新的 Fiber 树并收集了树中节点的更新 flags下一节我们将根据这些 flags 执行对应的 DOM 操作。 借鉴链接 https://juejin.cn/post/7347911786802511924 更新流程的目的 生成wip fiberNode树标记副作用flags 更新流程的步骤 递beginWork归completeWork 在 上一节 我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中beginWork 和 completeWork 两个方法起到了关键作用。beginWork 负责构建表示更新的 Fiber 树而 completeWork 则将这个 Fiber 树映射到实际的 DOM 结构上。接下来我们将深入实现这两个方法。 开发环境打印日志 首先在开发环境下增加 DEV 标识以便在开发环境中方便地打印日志 pnpm i -D -w rollup/plugin-replace安装完成后在 scripts/rollup/utils.js 中引入 // scripts/rollup/utils.js // ... import replace from rollup/plugin-replace ; // ... export function getBaseRollupPlugins ( { alias { __DEV__: true }, typescript {} } {} ) { return [ replace (alias), cjs (), ts (typescript)]; } 这样我们就可以在开发环境中打印日志了。 实现 beginWork 对于如下结构的reactElement: AB/ A/当进入A的beginWork时通过对比B的current fiberNode 与B的reactElement生成对应wip fiberNode beginWork 函数在向下遍历阶段执行根据 Fiber 节点的类型HostRoot、HostComponent、HostText分发任务给不同的处理函数处理具体节点类型的更新逻辑 export const beginWork (wip: FiberNode) {switch (wip.tag) {case HostRoot:return updateHostRoot(wip)case HostComponent:return updateHostComponent(wip)case HostText:return nulldefault:if (__DEV__) {console.warn(beginWork为实现的类型, wip)}break} }HostRoot /** 处理根节点的更新包括协调处理根节点的属性 以及子节点的更新逻辑 */ function updateHostRoot(wip: FiberNode) {const baseState wip.memoizedStateconst updateQueue wip.updateQueue as UpdateQueueElementconst pending updateQueue.shared.pendingupdateQueue.shared.pending null // 清空更新链表// 1.计算状态的最新值const { memoizedState } processUpdateQueue(baseState, pending) // 计算待更新状态的最新值wip.memoizedState memoizedState // 更新协调后的状态最新值// 2. 创造子fiberNodeconst nextChildren wip.memoizedState // 获取 children 属性reconcileChildren(wip, nextChildren) // 处理根节点的子节点可能会递归调用其他协调函数// 返回经过协调后的新的子节点链表return wip.child }表示根节点即应用的最顶层节点调用 updateHostRoot 函数处理根节点的更新包括协调处理根节点的属性以及子节点的更新逻辑调用 reconcileChildren 函数处理根节点的子节点可能会递归调用其他协调函数返回 workInProgress.child 表示经过协调后的新的子节点链表 HostComponent function updateHostComponent(wip: FiberNode) {const nextProps wip.pendingProps// 创造子fiberNodeconst nextChildren nextProps.children // 获取Dom的children属性reconcileChildren(wip, nextChildren) // 处理原生 DOM 元素的子节点更新可能会递归调用其他协调函数return wip.child }表示原生 DOM 元素节点例如 div、span 等调用 updateHostComponent 函数处理原生 DOM 元素节点的更新负责协调处理属性和子节点的更新逻辑调用 reconcileChildren 函数处理原生 DOM 元素的子节点更新返回 workInProgress.child 表示经过协调后的新的子节点链表 HostText 表示文本节点即 DOM 中的文本内容例如 p123/p 中的 123调用 updateHostText 函数协调处理文本节点的内容更新返回 null 表示已经是叶子节点没有子节点了 其中 reconcileChildren 函数的作用是通过对比子节点的 current FiberNode 与 子节点的 ReactElement来生成子节点对应的 workInProgress FiberNode。current 是与视图中真实 UI 对应的 Fiber 树workInProgress 是触发更新后正在 Reconciler 中计算的 Fiber 树。 function reconcileChildren(wip: FiberNode, children?: ReactElementType) {const current wip.alternateif (current ! null) {// updatewip.child reconcileChildFibers(wip, current?.child, children)} else {// mountwip.child mountChildFibers(wip, null, children)} }reconcileChildren 函数中调用了 reconcileChildFibers 和 mountChildFibers 两个函数它们分别负责处理更新阶段和首次渲染阶段的子节点协调。 reconcileChildFibers: reconcileChildFibers 函数作用于组件的更新阶段即当组件已经存在于 DOM 中需要进行更新时。主要任务是协调处理当前组件实例的子节点对比之前的子节点current和新的子节点workInProgress之间的变化。根据子节点的类型和 key 进行对比决定是复用、更新、插入还是删除子节点最终形成新的子节点链表。 mountChildFibers: mountChildFibers 函数作用于组件的首次渲染阶段即当组件第一次被渲染到 DOM 中时。主要任务是协调处理首次渲染时组件实例的子节点。但此时是首次渲染没有之前的子节点所以主要是创建新的子节点链表。 // packages/react-reconciler/src/childFiber.ts /** 实现生成子节点fiber 以及标记Flags的过程 */import { ReactElementType } from shared/ReactTypes import { FiberNode, createFiberFromElement } from ./fiber import { REACT_ELEMENT_TYPE } from shared/ReactSymbols import { HostText } from ./workTags import { Placement } from ./fiberFlagsfunction ChildrenReconciler(shouldTrackEffects: boolean) {/** 处理单个 Element 节点的情况对比 currentFiber 与 ReactElement生成 workInProgress FiberNode */function reconcileSingleElement(returnFiber: FiberNode,currentFiber: FiberNode | null,element: ReactElementType) {// 根据element创建fiberconst fiber createFiberFromElement(element)fiber.return returnFiberreturn fiber}/** 处理文本节点的情况对比 currentFiber 与 ReactElement生成 workInProgress FiberNode */function reconcileSingleTextNode(returnFiber: FiberNode,currentFiber: FiberNode | null,content: string | number) {const fiber new FiberNode(HostText, { content }, null)fiber.return returnFiberreturn fiber}/** 为 Fiber 节点添加更新 flags */function placeSingleChild(fiber: FiberNode) {// 优化策略首屏渲染且追踪副作用时才添加更新 flagsif (shouldTrackEffects fiber.alternate null) {fiber.flags | Placement}return fiber}// 闭包根据 shouldTrackSideEffects 返回不同 reconcileChildFibers 的实现return function reconcileChildFibers(returnFiber: FiberNode,currentFiber: FiberNode | null,newChild?: ReactElementType) {// 判断当前fiber的类型// 1. 单个 Element 节点if (typeof newChild object newChild ! null) {switch (newChild.$$typeof) {case REACT_ELEMENT_TYPE:return placeSingleChild(reconcileSingleElement(returnFiber, currentFiber, newChild))default:if (__DEV__) {console.warn(未实现的reconcile类型, newChild)}break}}// TODO 2. 多个 Element 节点 ul li*3// 3. HostText 节点if (typeof newChild string || typeof newChild number) {return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFiber, newChild))}// 4. 其他if (__DEV__) {console.warn(未实现的reconcile类型, newChild)}return null} }/** 处理更新阶段的子节点协调组件的更新阶段中追踪副作用*/ export const reconcileChildFibers ChildrenReconciler(true) /** 处理首次渲染阶段的子节点协调首屏渲染阶段中不追踪副作用只对根节点执行一次 DOM 插入操作*/ export const mountChildFibers ChildrenReconciler(false)// packages/react-reconciler/src/fiber.ts // .../** 根据element创建fiber并返回 */ export function createFiberFromElement(element: ReactElementType) {const { type, key, props } elementlet fiberTag: WorkTag FunctionComponentif (typeof type string) {// div/ type: divfiberTag HostComponent} else if (typeof type ! function __DEV__) {console.warn(未定义的type类型, element)}// 创建 fiber 节点const fiber new FiberNode(fiberTag, props, key)fiber.type typereturn fiber }beginWork性能优化策略 考虑如下结构的reacetElement: divp练习时长/pspan两年半/span /div理论上mount流程完毕后包含的flags: 两年半 PlacementSpan Placement练习时长 PlacementP PlacementDiv Placement 相比执行5次Placement我们可以构建好离屏DOM树后对div执行1次Placement操作 实现 completeWork 需要解决的问题 对于 Host 类型 fiberNode: 构建离屏Dom树标记 Update flag (TODO) completeWork 函数在向上遍历阶段执行根据 Fiber 节点的类型HostRoot、HostComponent、HostText 等构建 DOM 节点收集更新 flags并根据更新 flags 执行不同的 DOM 操作 HostComponent: 表示原生 DOM 元素节点构建 DOM 节点并调用 appendAllChildren 函数将 DOM 插入到 DOM 树中收集更新 flags并根据更新 flags 执行不同的 DOM 操作例如插入新节点、更新节点属性、删除节点等 HostText: 表示文本节点构建 DOM 节点并将 DOM 插入到 DOM 树中收集更新 flags根据 flags 的值更新文本节点的内容 HostRoot: 表示根节点会执行一些与根节点相关的最终操作例如处理根节点的属性确保整个应用更新完毕 export const completeWork (wip: FiberNode) {const newProps wip.pendingPropsconst current wip.alternateswitch (wip.tag) {case HostComponent:if (current ! null wip.stateNode) {//update} else {// mount 构建离屏的 Dom 树// 1. 构建 Domconst instance createInstance(wip.type, newProps)// 2. 将Dom插入到Dom树中appendAllChildren(instance, wip)wip.stateNode instance}bubbleProperties(wip)return nullcase HostText:if (current ! null wip.stateNode) {//update} else {// mount// 1. 构建 Domconst instance createTextInstance(newProps.content)wip.stateNode instance}bubbleProperties(wip)return nullcase HostRoot:bubbleProperties(wip)return nulldefault:if (__DEV__) {console.warn(completeWork未实现的类型, wip)}break} }其中appendAllChildren 函数负责递归地将组件的子节点添加到指定的 parent 中它通过深度优先遍历 workInProgress 的子节点链表处理每个子节点的类型。先处理当前节点的所有子节点再处理兄弟节点。 如果它是原生 DOM 元素节点或文本节点则将其添加到父节点中如果是其他类型的组件节点并且有子节点则递归处理其子节点。 // packages/react-reconciler/src/completeWork.ts // ... function appendAllChildren(parent: FiberNode, wip: FiberNode) {let node wip.child// 递归插入while (node ! null) {if (node?.tag HostComponent || node?.tag HostText) {appendInitialChild(parent, node?.stateNode)} else if (node.child ! null) {node.child.return nodenode node.childcontinue}// 终止条件if (node wip) {return}// 子节点结束开始处理兄弟节点while (node.sibling null) {// 1.当前节点无兄弟节点if (node.return null || node.return wip) {return}node node?.return}// 2.当前节点有兄弟节点node.sibling.return node.returnnode node.sibling} }completeWork 性能优化策略 flags分布在不同fiberNode中如何快速他们 利用completeWork向上遍历(归)的流程将子fiberNode的flags冒泡到父fiberNode 创建 bubbleProperties 函负责在 completeWork 函数向上遍历的过程中通过向上冒泡子节点的 flags将所有更新 flags 收集到根节点。主要包含以下步骤 从当前需要冒泡属性的 Fiber 节点开始检查是否有需要冒泡的属性。如果当前节点有需要冒泡的属性将这些属性冒泡到父节点的 subtreeFlags 或其他适当的属性中。递归调用 bubbleProperties 函数处理父节点将属性继续冒泡到更上层的祖先节点直至达到根节点。 // packages/react-reconciler/src/completeWork.ts // .../** 收集更新 flags将子 FiberNode 的 flags 冒泡到父 FiberNode 上 */ function bubbleProperties(wip: FiberNode) {let subtreeFlags NoFlagslet child wip.childwhile (child ! null) {subtreeFlags | child.subtreeFlagssubtreeFlags | child.flagschild.return wipchild child.sibling}wip.subtreeFlags | subtreeFlags }位运算简介 flags 是 React 中很重要的一环具体作用是通过二进制在每个 Fiber 节点保存其本身与子节点的 flags。在保存与处理 flags 时使用了一些二进制运算符我们来复习一下 1. | 运算 | 运算的两个位都为 0 时结果才为 0 1 | 1 11 | 0 10 | 0 0 React 利用了 | 运算符的特性来存储 flags如 ts 复制代码 const NoFlags /* */ 0b0000000;const PerformedWork /* */ 0b0000001;const Placement /* */ 0b0000010;const Update /* */ 0b0000100;const ChildDeletion /* */ 0b0001000;const flags Placement | Update; //此时 flags 0b00001102. 运算 运算的两个位都为 1 时结果才为 1 1 1 11 0 00 0 0 React 中会用一个 flags 某一个 flag来判断 flags 中是否包含某一个 flag如 ts 复制代码 const flags Placement | Update; //此时 flags 0b0000110Boolean(flags Placement); // true, 说明 flags 中包含 PlacementBoolean(flags ChildDeletion); // false, 说明 flags 中不包含 ChildDeletion3. ~ 运算 运算符会把每一位取反0 变 11 变 0 ~1 0~0 1 在 React 中~ 运算符同样是常用操作如 ts 复制代码 let flags Placement | Update; //此时 flags 0b0000110flags ~Placement; //此时 flags 0b0000100通过 ~ 运算符与 运算符的结合从 flags 中删除了 Placement 这个 flag。 至此我们就实现了 React 协调阶段中的 beginWork 和 completeWork 函数生成了一棵表示更新的 Fiber 树并收集了树中节点的更新 flags下一节我们将根据这些 flags 执行对应的 DOM 操作。 借鉴链接 https://juejin.cn/post/7347911786802511924
http://www.pierceye.com/news/715829/

相关文章:

  • 福建厦门网站建设公司网站代码素材建设
  • 广州网络公司建站e语言可以做网站吗
  • 不想用原来的网站模板了就用小偷工具采集了一个可是怎么替换seo顾问张智伟
  • 效果好的徐州网站开发建设网站怎么学
  • 上海网站设计要多少钱建设银行个人网站打不开
  • 哪个网站做欧洲旅行比较好东营网站制作
  • 做pc端网站效果wordpress js 添加图片
  • 给装修公司做网站商标设计大全
  • 深圳做网站公司有哪些地方国际形势最新消息
  • 企业网站建设管理平台石家庄平山网站推广优化
  • 免费asp网站模板带后台网站建设需求调研通知
  • 浙江二建建设集团有限公司网站微信哪里可以做视频网站
  • wordpress阿里百秀5.2广州网站排名专业乐云seo
  • 网站建设 上海网站福州最好的网站建设公司
  • 兴力网站建设企业宣传网站在哪里做
  • 网站了建设pc官网 和手机网站
  • wordpress导航网站模板下载wordpress 关闭搜索引擎
  • 网站架构的优化wordpress企业主题免费下载
  • 分类信息网站手机版自学编程从哪学起
  • 网站目录 index.html京伦科技网站做的怎么样
  • 学做简单网站视频教程济源建设网站
  • 一个网站开发成本网店推广方案范文
  • 为什么要做seo盐城网站优化
  • 网站策划方案ppt站长查询域名
  • 网站开发需要哪些流程wordpress 添加widget
  • 在线报名网站建设汉字logo设计生成器
  • 移动网站和桌面网站区别烟台网站设计制作公司电话
  • 遵义网站建设网站定制wordpress主题多少钱
  • 外贸网站如何做推广是什么意思长沙制作公园仿竹护栏多少钱一米
  • seo网站有优化培训吗小程序商城开发华网天下优秀