React19源码系列之 Diff算法

发布于:2025-05-16 ⋅ 阅读:(6) ⋅ 点赞:(0)

在之前文章中root.render执行的过程,beginWork函数是渲染过程的核心,其针对不同类型的fiber进行不同的更新处理,在FunctionComponent(函数组件)中,会针对新旧fiber进行对比处理生成新fiber。因此此次就详细记录一下新旧节点对比生成新fiber的过程,即diff 的过程。


其实react的 diff 方法无法是首次渲染还是更新的情况下都是调用 reconcileChildFibersImpl函数。

reconcileChildren

reconcileChildren 函数是 React 协调过程中的核心函数之一,主要用于协调新旧 Fiber 节点的子节点。在 React 的渲染流程中,当一个 Fiber 节点需要更新其子节点时,该函数会根据是否存在 旧的 Fiber 节点(current),选择不同的方式来处理子节点的更新,最终将处理后的子 Fiber 节点挂载到 workInProgress 节点上。

function reconcileChildren(
  current: Fiber | null,// 表示旧的 Fiber 节点。
  workInProgress: Fiber,// 表示当前正在处理的新 Fiber 节点
  nextChildren: any,// 表示新的子元素集合,通常是组件返回的 JSX 元素或子组件。
  renderLanes: Lanes,// 渲染的优先级车道。
) {
  if (current === null) {
    workInProgress.child = mountChildFibers(
      workInProgress,
      null,
      nextChildren,
      renderLanes,
    );
  } else {
    workInProgress.child = reconcileChildFibers(
      workInProgress,
      current.child,
      nextChildren,
      renderLanes,
    );
  }
}

mountChildFibers函数和 reconcileChildFibers 函数都有调用高阶函数 createChildReconciler 返回的一个函数。

const mountChildFibers: ChildReconciler = createChildReconciler(false);
const reconcileChildFibers: ChildReconciler = createChildReconciler(true);

createChildReconciler

createChildReconciler 函数是一个高阶函数,其主要作用是创建并返回一个用于协调子 Fiber 节点的函数 reconcileChildFibers。

function createChildReconciler(
  // shouldTrackSideEffects首次渲染为false,更新为true
  shouldTrackSideEffects: boolean,
): ChildReconciler {
  //。。。

  // function reconcileChildFibers(){}
  return reconcileChildFibers;
}


reconcileChildFibers

reconcileChildFibers 函数主要用于对比新旧子节点,生成新的 Fiber 节点树,以此实现 React 组件树的更新。主要实现是调用内部的 reconcileChildFibersImpl 函数完成调和操作,最终返回 新的第一个子 Fiber 节点。

函数参数含义:

  • returnFiber,父 Fiber 节点。
  • currentFirstChild,当前的子 Fiber 节点。
  • newChild,新的子节点。
  • lanes,渲染优先级。
    function reconcileChildFibers(
      returnFiber: Fiber,// 父节点fiber
      currentFirstChild: Fiber | null,//当前父 Fiber 节点的第一个子 Fiber 节点,如果没有子节点则为 null。
      newChild: any,// 新的节点
      lanes: Lanes,// 渲染优先级
    ): Fiber | null {
      try {
        // 根据新旧子节点的差异生成新的 Fiber 节点树,并返回第一个子 Fiber 节点。
        const firstChildFiber = reconcileChildFibersImpl(
          returnFiber,
          currentFirstChild,
          newChild,
          lanes,
        );
        return firstChildFiber;
      }catch{
        
      }
    }

    reconcileChildFibersImpl

    根据新子节点的类型(如 React 元素、数组、可迭代对象、Promise 等),调用相应的调和函数来生成新的子 Fiber 节点,并返回第一个子 Fiber 节点或null。

    function reconcileChildFibersImpl(
      returnFiber: Fiber,// 当前正在处理的父 Fiber 节点。
      currentFirstChild: Fiber | null,// 当前父 Fiber 节点的第一个子 Fiber 节点,如果没有子节点则为 null。
      newChild: any,//新的子节点信息,可以是不同类型的数据,如 React 元素、数组、可迭代对象等。
      lanes: Lanes,// 渲染优先级车道
    ): Fiber | null {
    
      // 判断新子节点是否为无 key 的顶级 Fragment 组件类型,如果是,则将新子节点更新为其 props.children,因为 Fragment 本身只是一个占位符,实际的子节点内容在其 props.children 中。
      const isUnkeyedTopLevelFragment =
        typeof newChild === 'object' &&
        newChild !== null &&
        newChild.type === REACT_FRAGMENT_TYPE &&
        newChild.key === null;
    
      // fragment  占位组件,将其child设置为newChild
      if (isUnkeyedTopLevelFragment) {
        // validateFragmentProps(newChild, null, returnFiber);
        newChild = newChild.props.children;
      }
    
      // Handle object types
      // 处理对象类型的子节点
      if (typeof newChild === 'object' && newChild !== null) {
        
        switch (newChild.$$typeof) {
            // 根据 $$typeof 判断 React 元素类型
          case REACT_ELEMENT_TYPE: {
            // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
            
            const firstChild = placeSingleChild(
              reconcileSingleElement(
                returnFiber,
                currentFirstChild,
                newChild,
                lanes,
              ),
            );
            // currentDebugInfo = prevDebugInfo;
            return firstChild;
          }
    
            // 处理 React Portal 类型
          case REACT_PORTAL_TYPE:
            return placeSingleChild(
              reconcileSinglePortal(
                returnFiber,
                currentFirstChild,
                newChild,
                lanes,
              ),
            );
    
            // 处理 React Lazy 类型
          case REACT_LAZY_TYPE: {
            // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
            let result;
            // newChild._payload 是传递给初始化函数的数据
            const payload = newChild._payload;
            // newChild._init 是懒加载组件的初始化函数。
            const init = newChild._init;
            // 调用初始化函数 init 并传入 payload,以获取实际的组件。通常,init 函数会动态导入组件并返回。
            result = init(payload);
    
            // reconcileChildFibersImpl:这是一个内部函数,用于调和子 Fiber 节点。它会比较新旧 Fiber 树,找出差异并更新 Fiber 树。
            const firstChild = reconcileChildFibersImpl(
              returnFiber,
              currentFirstChild,
              result,
              lanes,
            );
            // currentDebugInfo = prevDebugInfo;
            return firstChild;
          }
            
        }
    
        // 处理数组类型的子节点
        if (isArray(newChild)) {
          // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
          const firstChild = reconcileChildrenArray(
            returnFiber,
            currentFirstChild,
            newChild,
            lanes,
          );
          // currentDebugInfo = prevDebugInfo;
          return firstChild;
        }
    
        // 处理可迭代类型的子节点
        if (getIteratorFn(newChild)) {
          // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
          const firstChild = reconcileChildrenIteratable(
            returnFiber,
            currentFirstChild,
            newChild,
            lanes,
          );
          // currentDebugInfo = prevDebugInfo;
          return firstChild;
        }
    
        // 处理异步可迭代类型的子节点
        if (
          enableAsyncIterableChildren &&
          typeof newChild[ASYNC_ITERATOR] === 'function'
        ) {
          // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
          const firstChild = reconcileChildrenAsyncIteratable(
            returnFiber,
            currentFirstChild,
            newChild,
            lanes,
          );
          // currentDebugInfo = prevDebugInfo;
          return firstChild;
        }
    
        // 处理 Promise 类型的子节点
        if (typeof newChild.then === 'function') {
          const thenable: Thenable<any> = (newChild: any);
          // const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);
            const firstChild = reconcileChildFibersImpl(
              returnFiber,
              currentFirstChild,
              unwrapThenable(thenable),
              lanes,
            );
            // currentDebugInfo = prevDebugInfo;
            return firstChild;
          }
    
        // 处理 React Context 类型
          if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
            const context: ReactContext<mixed> = (newChild: any);
            return reconcileChildFibersImpl(
              returnFiber,
              currentFirstChild,
              readContextDuringReconciliation(returnFiber, context, lanes),
              lanes,
            );
          }
    
          // throwOnInvalidObjectType(returnFiber, newChild);
        }
    
      // 处理字符串、数字和大整数类型的子节点
        if (
          (typeof newChild === 'string' && newChild !== '') ||
          typeof newChild === 'number' ||
          typeof newChild === 'bigint'
        ) {
          return placeSingleChild(
            reconcileSingleTextNode(
              returnFiber,
              currentFirstChild,
              // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint
              '' + newChild,
              lanes,
            ),
          );
        }
    
        // Remaining cases are all treated as empty.
      // 对于其他未处理的情况,将其视为空节点,调用 deleteRemainingChildren 函数删除当前父节点的所有剩余子节点,并返回 null。
        return deleteRemainingChildren(returnFiber, currentFirstChild);
      }

    情况1:新节点是object类型且不为null

    1-1 检查newChild.$$typeof为REACT_ELEMENT_TYPE

    case REACT_ELEMENT_TYPE: {
    // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
            
    const firstChild = placeSingleChild(
       reconcileSingleElement(
           returnFiber,
           currentFirstChild,
           newChild,
           lanes,
       ),
      );
      // currentDebugInfo = prevDebugInfo;
       return firstChild;
    }


    reconcileSingleElement

    reconcileSingleElement 函数主要是将一个新的 React 元素与现有的子 Fiber 节点进行比较,根据比较结果决定是复用现有的 Fiber 节点,还是创建一个新的 Fiber 节点。

    处理步骤:

    1、while循环遍历fiber的子节点,下一个处理的节点是fiber.sibling。
    2、检查新旧fiber的key 。

    • key相同:    
      • 如果是fragment,删除当前子 Fiber 节点之后的所有兄弟节点,复用其子节点,返回。   
      • 如果是lazy:删除当前子 Fiber 节点之后的所有兄弟节点,复用,处理ref,返回。   
      • 其他:删除当前子 Fiber 节点及其之后的所有兄弟节点,然后跳出循环。
    • key不同:删除当前子 Fiber 节点及其之后的所有兄弟节点,然后跳出循环。

    3、若新元素是 Fragment 类型,调用 createFiberFromFragment 函数创建新的 Fiber 节点,设置其 return 属性指向父 Fiber 节点,最后返回该节点。
    4、若不是 Fragment 类型,调用 createFiberFromElement 函数创建新的 Fiber 节点,处理 ref,设置其 return 属性指向父 Fiber 节点,最后返回该节点。

    function reconcileSingleElement(
      returnFiber: Fiber,// 当前元素的父 Fiber 节点。
      currentFirstChild: Fiber | null,// 当前的第一个子 Fiber 节点,如果没有则为 null。
      element: ReactElement,// 要调和的 React 元素。即新元素
      lanes: Lanes,// 渲染优先级车道。
    ): Fiber {
      //  React 元素的 key 属性,key 用于帮助 React 识别哪些元素发生了变化,提高调和效率。
      const key = element.key;
      
      // 用于遍历当前的子 Fiber 节点。
      let child = currentFirstChild;
      
      while (child !== null) {
        // the first item in the list.
        // 当前子 Fiber 节点的 key 与新元素的 key 相同,继续检查元素类型。
        if (child.key === key) {
          const elementType = element.type;
          // 如果新元素是fragment类型
          if (elementType === REACT_FRAGMENT_TYPE) {
            
            if (child.tag === Fragment) {
             // 省略代码,看后续代码片段
              return existing;
            }
          } else {
            // 懒加载组件
            if (
              child.elementType === elementType  ||
              (typeof elementType === 'object' &&
                elementType !== null &&
                elementType.$$typeof === REACT_LAZY_TYPE &&
                resolveLazy(elementType) === child.type)
            ) {
             // 省略代码,看代码片段
          
              return existing;
            }
          }
          // Didn't match.
          deleteRemainingChildren(returnFiber, child);
          // 跳出循环
          break;
        } else {
          // key 不匹配,标记删除
          deleteChild(returnFiber, child);
        }
        //移动到下一个子 Fiber 节点
        child = child.sibling;
      }
    
      if (element.type === REACT_FRAGMENT_TYPE) {
        // 创建新的 Fiber 节点
        const created = createFiberFromFragment(
          element.props.children,
          returnFiber.mode,
          lanes,
          element.key,
        );
        created.return = returnFiber;
      
        // validateFragmentProps(element, created, returnFiber);
        return created;
        
      } else {
        
        // 创建新的 Fiber 节点
        const created = createFiberFromElement(element, returnFiber.mode, lanes);
        coerceRef(created, element);
        created.return = returnFiber;
    
        return created;
      }
    }

     代码片段:

    if (child.tag === Fragment) {
      // 标记要删除child的所有兄弟节点
      deleteRemainingChildren(returnFiber, child.sibling);
    
      // 复用fragment下的子节点
      const existing = useFiber(child, element.props.children);
      
     //设置其return属性即父节点
      existing.return = returnFiber;
     
      // validateFragmentProps(element, existing, returnFiber);
      return existing;
    }

    为什么child.tag = Fragment,要删除 child 的所有兄弟节点?

    Fragment 是 React 里用于将多个子元素分组但又不引入额外 DOM 节点的一种方式。它允许你在不添加多余父元素的情况下返回多个元素。

    从结构层面来看,Fragment 可以当作一个逻辑上的容器,它本身不会在 DOM 树中产生额外节点。所以在 Fiber 树里,Fragment 节点期望能直接包含其子元素,而不应该有其他兄弟节点与其并列。

    Fiber 调和过程的目的是找出新旧 Fiber 树之间的差异,然后最小化 DOM 操作来更新页面。当遇到 Fragment 节点时,React 会认为 Fragment 应该是当前层级下的唯一逻辑容器。如果 Fragment 有兄弟节点,可能会打乱这种逻辑结构,使得调和过程变得复杂。

    代码片段: 

    if (
      // 检查当前 child 节点的 elementType 是否与新元素的 elementType 相同。elementType 通常表示元素的类型,比如函数组件、类组件或者 HTML 标签名等。如果相同,说明可能可以复用这个节点。
      child.elementType === elementType  ||
    
      // 懒加载组件
      (typeof elementType === 'object' &&
        elementType !== null &&
        elementType.$$typeof === REACT_LAZY_TYPE &&
        resolveLazy(elementType) === child.type)
      
    ) {
      // 标记删除所有的兄弟节点
      deleteRemainingChildren(returnFiber, child.sibling);
    
      // 复用child节点
      const existing = useFiber(child, element.props);
    
      // 处理ref
      coerceRef(existing, element);
      
      existing.return = returnFiber;
    
      return existing;
    }

    createFiberFromElement

    createFiberFromElement 函数的主要功能是依据传入的 React 元素(ReactElement)创建一个对应的 Fiber 节点。

    函数参数说明:

    • element: ReactElement:待转换的 React 元素,它包含了组件的类型、属性、key 等信息。
    • mode: TypeOfMode:节点的模式,用于控制该节点及其子节点的行为,像是否启用并发模式等。
    • lanes: Lanes:渲染优先级车道,用来确定该节点的渲染优先级。
       function createFiberFromElement(
        element: ReactElement,
        mode: TypeOfMode,
        lanes: Lanes,
      ): Fiber {
         // 初始owner
        let owner = null;
         
      // 获取 React 元素的类型,可能是函数组件、类组件或者原生 DOM 元素类型。
        const type = element.type;
      
      // 获取 React 元素的 key 属性,key 用于辅助 React 识别哪些元素发生了变化,提升调和效率。
        const key = element.key;
          
       // 获取 React 元素的属性,也就是传递给组件的新属性。
        const pendingProps = element.props;
      
        const fiber = createFiberFromTypeAndProps(
          type,// 元素类型
          key,
          pendingProps,
          owner,
          mode,// 模式,并发模式
          lanes,// 渲染优先级车道
        );
      
        return fiber;
      }

      createFiberFromTypeAndProps

      createFiberFromTypeAndProps 函数的主要功能是根据传入的组件类型、属性等信息,创建相应类型的 Fiber 节点。在 React 的 Fiber 架构中,Fiber 节点是协调和渲染过程的核心数据结构,该函数会根据不同的组件类型(如函数组件、类组件、各种特殊组件等)设置 Fiber 节点的属性和类型标签,最终返回创建好的 Fiber 节点,为后续的渲染和更新操作提供基础。

      函数参数说明

      • type: any:React 组件的类型,可以是函数、类、字符串(代表原生 DOM 元素)或特殊的 React 类型(如 FragmentContext 等)。
      • key: null | string:节点的 key 属性,用于帮助 React 识别哪些元素发生了变化,提高调和效率。
      • pendingProps: any:组件的待处理属性。
      • owner: null | ReactComponentInfo | Fiber:创建该组件的所有者,可能是 nullReactComponentInfoFiber 节点。
      • mode: TypeOfMode:节点的模式,用于控制该节点及其子节点的行为,例如是否启用并发模式等。
      • lanes: Lanes:渲染优先级车道,用于确定该节点的渲染优先级。
       function createFiberFromTypeAndProps(
        type: any, // React$ElementType
        key: null | string,
        pendingProps: any,
        owner: null | ReactComponentInfo | Fiber,
        mode: TypeOfMode,
        lanes: Lanes,
      ): Fiber {
      
        // fiberTag 初始化为 FunctionComponent,表示默认情况下将组件视为函数组件。
         // fiberTag代表节点类型
        let fiberTag = FunctionComponent;
      
         // 存储组件类型
        let resolvedType = type;
         
        if (typeof type === 'function') {
          // 如果 type 是函数类型,调用 shouldConstruct 函数判断该函数是否为类组件的构造函数。如果是,则将 fiberTag 设置为 ClassComponent。
          if (shouldConstruct(type)) {
            fiberTag = ClassComponent;
          } 
          
        } else if (typeof type === 'string') {
        // 省略代码。。。看后面的代码片段分析
          
        } else {
          // 创建不同类型的fiber节点
          getTag: switch (type) {
              // 当 type 为 REACT_FRAGMENT_TYPE 时,表示当前元素是一个 Fragment。Fragment 是 React 中用于分组多个子元素而不引入额外 DOM 节点的方式。
            case REACT_FRAGMENT_TYPE:
              return createFiberFromFragment(pendingProps.children, mode, lanes, key);
              // 当 type 为 REACT_STRICT_MODE_TYPE 时,表示当前元素是一个 StrictMode 组件。StrictMode 用于在开发模式下帮助发现潜在的问题,如不安全的生命周期方法、过时的 API 使用等。
            case REACT_STRICT_MODE_TYPE:
              fiberTag = Mode;
              mode |= StrictLegacyMode;
              if (disableLegacyMode || (mode & ConcurrentMode) !== NoMode) {
                // Strict effects should never run on legacy roots
                mode |= StrictEffectsMode;
                if (
                  enableDO_NOT_USE_disableStrictPassiveEffect &&
                  pendingProps.DO_NOT_USE_disableStrictPassiveEffect
                ) {
                  mode |= NoStrictPassiveEffectsMode;
                }
              }
              break;
      
              // 当 type 为 REACT_PROFILER_TYPE 时,表示当前元素是一个 Profiler 组件。Profiler 用于测量 React 应用的性能,记录组件渲染的时间。
            case REACT_PROFILER_TYPE:
              return createFiberFromProfiler(pendingProps, mode, lanes, key);
      
          // :当 type 为 REACT_SUSPENSE_TYPE 时,表示当前元素是一个 Suspense 组件。Suspense 用于处理异步加载的组件,在组件加载完成之前显示一个加载指示器。
            case REACT_SUSPENSE_TYPE:
              return createFiberFromSuspense(pendingProps, mode, lanes, key);
      
              // 省略一些代码。。
              
            // Fall through
            default: {
              if (typeof type === 'object' && type !== null) {
                switch (type.$$typeof) {
                    
      // 当 type.$$typeof 为 REACT_PROVIDER_TYPE 时,表明这是一个 Context.Provider 组件。
                  case REACT_PROVIDER_TYPE:
                    if (!enableRenderableContext) {
                      fiberTag = ContextProvider;
                      break getTag;
                    }
                    
                  // Fall through
        // 当 type.$$typeof 为 REACT_CONTEXT_TYPE 时,代表这是一个 Context 对象。      
                  case REACT_CONTEXT_TYPE:
                    if (enableRenderableContext) {
                      fiberTag = ContextProvider;
                      break getTag;
                    } else {
                      fiberTag = ContextConsumer;
                      break getTag;
                    }
      // 当 type.$$typeof 为 REACT_CONSUMER_TYPE 时,说明这是一个 Context.Consumer 组件。
                  case REACT_CONSUMER_TYPE:
                    if (enableRenderableContext) {
                      fiberTag = ContextConsumer;
                      break getTag;
                    }
                  // Fall through
      // 当 type.$$typeof 为 REACT_FORWARD_REF_TYPE 时,表明这是一个使用 React.forwardRef 创建的组件。
                  case REACT_FORWARD_REF_TYPE:
                    fiberTag = ForwardRef;
             
                    break getTag;
                    
      // 当 type.$$typeof 为 REACT_MEMO_TYPE 时,意味着这是一个使用 React.memo 包装的组件。            
                  case REACT_MEMO_TYPE:
                    fiberTag = MemoComponent;
                    break getTag;
      
      // 当 type.$$typeof 为 REACT_LAZY_TYPE 时,表示这是一个使用 React.lazy 创建的懒加载组件。
                  case REACT_LAZY_TYPE:
                    fiberTag = LazyComponent;
                    resolvedType = null;
                    break getTag;
                }
              }
      
             
              let info = '';
              let typeString;
           
              typeString = type === null ? 'null' : typeof type;
              
              // 如果以上都不是,fiberTag表示错误组件
              fiberTag = Throw;
              pendingProps = new Error(
                'Element type is invalid: expected a string (for built-in ' +
                  'components) or a class/function (for composite components) ' +
                  `but got: ${typeString}.${info}`,
              );
              resolvedType = null;
            }
          }
        }
      
         // 创建fiber
        const fiber = createFiber(fiberTag, pendingProps, key, mode);
        fiber.elementType = type;
        fiber.type = resolvedType;
        fiber.lanes = lanes;
      
        return fiber;
      }

      可以看出组件lazy、memo、forwardRef、Provide、Consumer组件都是使用createFiber创建相应的fiber节点。

      代码片段:

      if (typeof type === 'string') {
        if (supportsResources && supportsSingletons) {
          // 获取宿主环境的上下文信息,这可能包含了一些与渲染环境相关的数据。
          const hostContext = getHostContext();
          
          // isHostHoistableType函数判断该元素是否为可提升的宿主类型
          fiberTag = isHostHoistableType(type, pendingProps, hostContext)
            ? HostHoistable// meta,title等
            : isHostSingletonType(type)
              ? HostSingleton 
              : HostComponent;
          
        } else if (supportsResources) {
          
          const hostContext = getHostContext();
          
          fiberTag = isHostHoistableType(type, pendingProps, hostContext)
            ? HostHoistable
            : HostComponent;
          
        } else if (supportsSingletons) {
          fiberTag = isHostSingletonType(type) ? HostSingleton : HostComponent;
          
        } else {
          fiberTag = HostComponent;
        }
      }

      例子:createContext的使用(Provider 和 Consumer)

      import { createContext } from 'react';
      
      const ThemeContext = createContext('light');
      
      function App() {
        const [theme, setTheme] = useState('light');
        // ...
        return (
          <ThemeContext.Provider value={theme}>
            <Page />
          </ThemeContext.Provider>
        );
      }
      function Button() {
        // 🟡 Legacy way (not recommended)
        return (
          <ThemeContext.Consumer>
            {theme => (
              <button className={theme} />
            )}
          </ThemeContext.Consumer>
        );
      }

       createFiberFromFragment

      createFiberFromFragment 函数用于创建一个表示 React Fragment 的 Fiber 节点。它通过调用 createFiber 函数初始化基本的 Fiber 结构,并设置其 lanes 属性以标记该 Fiber 的优先级。Fragment 是一种特殊的 React 元素,用于将多个子元素分组而不引入额外的 DOM 节点。

      函数参数说明:

      • Fragment:指定 Fiber 类型为 Fragment(对应 React 内部的 Fragment 标签类型)。
      • elements:Fragment 包含的子元素集合,通常是一个数组。
      • key:Fragment 的 key 值,用于在协调过程中识别元素。
      • mode:Fiber 的模式,决定了渲染行为(如并发模式、严格模式等)。
      function createFiberFromFragment(
        elements: ReactFragment,
        mode: TypeOfMode,
        lanes: Lanes,
        key: null | string,
      ): Fiber {
      // Fragment常量 为7
        const fiber = createFiber(Fragment, elements, key, mode);
        fiber.lanes = lanes;
        return fiber;
      }

      createFiberFromSuspense

      createFiberFromSuspense 函数用于创建一个表示 React Suspense 组件的 Fiber 节点。Suspense 是 React 中用于处理异步加载内容的特性,允许组件在等待数据时显示加载状态。该函数初始化了 Suspense 组件的基本 Fiber 结构,并设置了相关属性。

      参数说明:

      • SuspenseComponent:指定 Fiber 类型为 Suspense 组件(对应 React 内部的 Suspense 标签类型)。
      • pendingProps:Suspense 组件的属性,通常包含 fallback(加载状态内容)和子组件。
      • key:Suspense 组件的 key 值,用于在协调过程中识别元素。
      • mode:Fiber 的模式,决定了渲染行为(如并发模式、严格模式等)。
      function createFiberFromSuspense(
        pendingProps: any,
        mode: TypeOfMode,
        lanes: Lanes,
        key: null | string,
      ): Fiber {
        const fiber = createFiber(SuspenseComponent, pendingProps, key, mode);
        fiber.elementType = REACT_SUSPENSE_TYPE;
        fiber.lanes = lanes;
        return fiber;
      }

      1-2 检查newChild.$$typeof为REACT_PORTAL_TYPE

      1. 遍历现有的子 Fiber 节点。
      2. 检查新旧节点的key是否相同。
        1. key相同:
          1. 可复用:删除当前子 Fiber 节点之后的所有兄弟节点。复用当前子 Fiber 节点,并更新其 children 属性。复用节点的 return 属性指向父 Fiber 节点,返回复用节点。
          2. 不可复用:删除当前子 Fiber 节点之后的所有兄弟节点,并跳出循环。
        2. key不同:删除当前子 Fiber 节点之后的所有兄弟节点。
      3. 结束循环。
      4. 创建新的 Fiber 节点并返回。
         // 处理 React Portal 类型
       case REACT_PORTAL_TYPE:
         return placeSingleChild(
           reconcileSinglePortal(
             returnFiber,
             currentFirstChild,
             newChild,
             lanes,
           ),
         );

      reconcileSinglePortal

      reconcileSinglePortal 函数的主要作用是调和单个 ReactPortal 元素。在 React 中,Portal 是一种将子节点渲染到 DOM 树中当前组件层次结构之外位置的方式。该函数会尝试复用现有的 Fiber 节点,如果无法复用则创建一个新的 Fiber 节点,同时处理相关的兄弟节点删除操作。

      处理过程:

      1、遍历现有的子 Fiber 节点

      2、检查新旧节点的key是否相同

      • key相同:
        • 可复用:删除当前子 Fiber 节点之后的所有兄弟节点。复用当前子 Fiber 节点,并更新其 children 属性。复用节点的 return 属性指向父 Fiber 节点。返回复用节点
        • 不可复用:删除当前子 Fiber 节点之后的所有兄弟节点,并跳出循环。
      • key不同:删除当前子 Fiber 节点之后的所有兄弟节点。

      2、结束循环。

      3、创建新的 Fiber 节点,并返回

      function reconcileSinglePortal(
        returnFiber: Fiber,//:父 Fiber 节点,即当前 Portal 元素所属的父节点。
        currentFirstChild: Fiber | null,// 当前父节点的第一个子 Fiber 节点,可能为 null。
        portal: ReactPortal,// 新的 ReactPortal 元素,包含了要渲染的子节点以及目标容器信息。
        lanes: Lanes,// 渲染优先级车道,用于表示当前操作的优先级。
      ): Fiber {
        const key = portal.key;
        let child = currentFirstChild;
        while (child !== null) {
          if (child.key === key) {
            if (
              child.tag === HostPortal &&
              // 检查子节点的目标容器信息是否与 Portal 元素的目标容器信息相同。
              child.stateNode.containerInfo === portal.containerInfo &&
              // 检查子节点的实现方式是否与 Portal 元素的实现方式相同。
              child.stateNode.implementation === portal.implementation
            ) {
              deleteRemainingChildren(returnFiber, child.sibling);
              const existing = useFiber(child, portal.children || []);
              existing.return = returnFiber;
              return existing;
            } else {
              deleteRemainingChildren(returnFiber, child);
              break;
            }
          } else {
            deleteChild(returnFiber, child);
          }
          // 将 child 指针指向当前子节点的下一个兄弟节点,继续遍历。
          child = child.sibling;
        }
      
        const created = createFiberFromPortal(portal, returnFiber.mode, lanes);
        created.return = returnFiber;
        return created;
      }

      createFiberFromPortal

      createFiberFromPortal 函数的主要功能是依据给定的 ReactPortal 对象、模式和优先级车道,创建一个 HostPortal 类型的 Fiber 节点。ReactPortal 是 React 提供的一种特殊机制,它能让子组件渲染到 DOM 树中当前组件层次结构之外的位置。此函数会为 Portal 创建对应的 Fiber 节点,以便在 Fiber 架构里对其进行调和与渲染。

      function createFiberFromPortal(
        portal: ReactPortal,
        mode: TypeOfMode,
        lanes: Lanes,
      ): Fiber {
        const pendingProps = portal.children !== null ? portal.children : [];
        const fiber = createFiber(HostPortal, pendingProps, portal.key, mode);
        fiber.lanes = lanes;
        fiber.stateNode = {
          containerInfo: portal.containerInfo,
          pendingChildren: null, // Used by persistent updates
          implementation: portal.implementation,
        };
        return fiber;
      }
      

      1-3 检查newChild.$$typeof为REACT_LAZY_TYPE

        // 处理 React Lazy 类型
       case REACT_LAZY_TYPE: {
         // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
         let result;
         // newChild._payload 是传递给初始化函数的数据
         const payload = newChild._payload;
         // newChild._init 是懒加载组件的初始化函数。
         const init = newChild._init;
         // 调用初始化函数 init 并传入 payload,以获取实际的组件。通常,init 函数会动态导入组件并返回。
         result = init(payload);
      
         // reconcileChildFibersImpl:这是一个内部函数,用于调和子 Fiber 节点。它会比较新旧 Fiber 树,找出差异并更新 Fiber 树。
         const firstChild = reconcileChildFibersImpl(
           returnFiber,
           currentFirstChild,
           result,
           lanes,
         );
         // currentDebugInfo = prevDebugInfo;
         return firstChild;
       }

      1-4 检查newChild为数组类型(多个同级子节点)

       // 处理数组类型的子节点
       if (isArray(newChild)) {
         // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
         const firstChild = reconcileChildrenArray(
           returnFiber,
           currentFirstChild,
           newChild,
           lanes,
         );
         // currentDebugInfo = prevDebugInfo;
         return firstChild;
       }

      reconcileChildrenArray

      reconcileChildrenArray 函数是用于对比新旧子节点数组,找出它们之间的差异,然后根据这些差异更新 Fiber 树,以反映新的 UI 状态。它会对新旧子节点进行遍历和比较,执行插入、删除、移动等操作,并标记相应的副作用,最终返回新的第一个子 Fiber 节点。

      处理过程:

      1. 第一轮遍历:同步比较新旧子节点
      2. 如果新子节点遍历完,删除剩余的旧子节点,返回,结束。
      3. 如果旧子节点遍历完,创建剩余的新子节点。并将剩余的旧子节点存储到一个 Map 中
      4. 第二轮遍历:处理剩余的新子节点
      5. 删除剩余未使用的旧子节点
      function reconcileChildrenArray(
          returnFiber: Fiber,// 父节点
          currentFirstChild: Fiber | null,// 
          newChildren: Array<any>,
          lanes: Lanes,
        ): Fiber | null {
      
        // 用于存储已知的键集合,初始为 null。
          let knownKeys: Set<string> | null = null;
          // 存储新的第一个子 Fiber 节点,初始为 null。
          let resultingFirstChild: Fiber | null = null;
      
        // 存储上一个处理的新 Fiber 节点,初始为 null。
          let previousNewFiber: Fiber | null = null;
      
        // 指向当前旧的子 Fiber 节点,初始为 currentFirstChild。
          let oldFiber = currentFirstChild;
      
        // 记录最后一个被放置的节点的索引,初始为 0。
          let lastPlacedIndex = 0;
      
        // 用于遍历新子节点数组的索引,初始为 0。
          let newIdx = 0;
        // 存储下一个旧的子 Fiber 节点,初始为 null。
          let nextOldFiber = null;
      
         // 第一轮遍历:同步遍历新旧子节点
          for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
            if (oldFiber.index > newIdx) {
              nextOldFiber = oldFiber;
              oldFiber = null;
            } else {
              nextOldFiber = oldFiber.sibling;
            }
      
            // updateSlot 函数用于尝试复用旧的 Fiber 节点或创建新的 Fiber 节点。
            const newFiber = updateSlot(
              returnFiber,
              oldFiber,
              newChildren[newIdx],
              lanes,
            );
      
            // 如果 newFiber 为 null,说明当前位置没有匹配的节点,跳出循环。
            if (newFiber === null) {
              if (oldFiber === null) {
                oldFiber = nextOldFiber;
              }
              break;
            }
      
          // 需要跟踪副作用且旧的 Fiber 节点未被复用,则调用 deleteChild 函数删除旧的子节点。
            if (shouldTrackSideEffects) {
              if (oldFiber && newFiber.alternate === null) {
                deleteChild(returnFiber, oldFiber);
              }
            }
      
            // placeChild 函数用于确定新 Fiber 节点的插入位置,并更新 lastPlacedIndex。
            lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
            
            if (previousNewFiber === null) {
              // TODO: Move out of the loop. This only happens for the first run.
              resultingFirstChild = newFiber;
            } else {
              previousNewFiber.sibling = newFiber;
            }
            previousNewFiber = newFiber;
            oldFiber = nextOldFiber;
          }
      
      
        // 处理新子节点遍历完的情况
          if (newIdx === newChildren.length) {
           
            deleteRemainingChildren(returnFiber, oldFiber);
            return resultingFirstChild;
          }
      
         // 处理旧子节点遍历完的情况
          if (oldFiber === null) {
           
            for (; newIdx < newChildren.length; newIdx++) {
              const newFiber = createChild(returnFiber, newChildren[newIdx], lanes);
              if (newFiber === null) {
                continue;
              }
              lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
              
              if (previousNewFiber === null) {
                
                resultingFirstChild = newFiber;
              } else {
                previousNewFiber.sibling = newFiber;
              }
              previousNewFiber = newFiber;
            }
            return resultingFirstChild;
          }
      
          // Add all children to a key map for quick lookups.
        // 处理剩余的新旧子节点
          const existingChildren = mapRemainingChildren(oldFiber);
      
          // Keep scanning and use the map to restore deleted items as moves.
          for (; newIdx < newChildren.length; newIdx++) {
            const newFiber = updateFromMap(
              existingChildren,
              returnFiber,
              newIdx,
              newChildren[newIdx],
              lanes,
            );
            if (newFiber !== null) {
      
              if (shouldTrackSideEffects) {
                if (newFiber.alternate !== null) {
           
                  existingChildren.delete(
                    newFiber.key === null ? newIdx : newFiber.key,
                  );
                }
              }
              lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
              if (previousNewFiber === null) {
                resultingFirstChild = newFiber;
              } else {
                previousNewFiber.sibling = newFiber;
              }
              previousNewFiber = newFiber;
            }
          }
      
      
        // 删除剩余的旧子节点
          if (shouldTrackSideEffects) {
            existingChildren.forEach(child => deleteChild(returnFiber, child));
          }
      
          // if (getIsHydrating()) {
          //   const numberOfForks = newIdx;
          //   pushTreeFork(returnFiber, numberOfForks);
          // }
      
        // 返回新的第一个子 Fiber 节点
          return resultingFirstChild;
        }
      

      1-5 检查newChild为可迭代类型

          // 处理可迭代类型的子节点
          if (getIteratorFn(newChild)) {
            // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
            const firstChild = reconcileChildrenIteratable(
              returnFiber,
              currentFirstChild,
              newChild,
              lanes,
            );
            // currentDebugInfo = prevDebugInfo;
            return firstChild;
          }

      reconcileChildrenIterator

      reconcileChildrenIterator 函数的主要功能是对新旧子节点进行协调,以找出它们之间的差异,并根据这些差异更新 Fiber 树。该函数接收一个迭代器 newChildren 作为新的子节点来源,会将其与旧的子 Fiber 节点进行比较,然后执行插入、删除、移动等操作,最终返回新的第一个子 Fiber 节点。

      函数参数含义

      • returnFiber:类型为 Fiber,代表父 Fiber 节点,即当前处理的子节点所属的父节点。
      • currentFirstChild:类型为 Fiber | null,表示当前父 Fiber 节点的第一个子 Fiber 节点,如果没有子节点则为 null
      • newChildren:类型为 ?Iterator<mixed>,是一个迭代器对象,用于遍历新的子节点。
      • lanes:类型为 Lanes,表示渲染优先级,用于确定此次更新的优先级。

        处理过程:

        1、同步遍历新旧节点。

        2、处理新子节点遍历完的情况。如果完毕这里结束。

        3、处理旧子节点遍历完的情况。剩余新子节点新建。

        4、处理剩余的新旧子节点,依据剩余新子节点查询就节点map中可复用的。

        5、删除剩余的旧子节点。

        6、返回新的第一个子 Fiber 节点。

        function reconcileChildrenIterator(
            returnFiber: Fiber,
            currentFirstChild: Fiber | null,
            newChildren: ?Iterator<mixed>,
            lanes: Lanes,
          ): Fiber | null {
            if (newChildren == null) {
              throw new Error('An iterable object provided no iterator.');
            }
        
          // 存储新fiber的第一个子节点
            let resultingFirstChild: Fiber | null = null;
          // 存储上一个处理的新 Fiber 节点,用于构建新的 Fiber 节点链表。
            let previousNewFiber: Fiber | null = null;
        
          // 旧fiber
            let oldFiber = currentFirstChild;
          // 记录最后一个放置的 Fiber 节点的索引,用于判断节点是否需要移动。
            let lastPlacedIndex = 0;
            let newIdx = 0;
            let nextOldFiber = null;// 下一个fiber节点
        
            // 用于存储已知的 key,初始为 null。
            let knownKeys: Set<string> | null = null;
        
          // 下一个新子节点
            let step = newChildren.next();
          // 1、同步遍历新旧节点
            for (
              ;
              oldFiber !== null && !step.done;
              newIdx++, step = newChildren.next()
            ) {
              if (oldFiber.index > newIdx) {
                nextOldFiber = oldFiber;
                oldFiber = null;
              } else {
                nextOldFiber = oldFiber.sibling;
              }
              const newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);
              if (newFiber === null) {
                if (oldFiber === null) {
                  oldFiber = nextOldFiber;
                }
                break;
              }
        
              lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
              if (previousNewFiber === null) {
                
                resultingFirstChild = newFiber;
              } else {
             
                previousNewFiber.sibling = newFiber;
              }
              previousNewFiber = newFiber;
              oldFiber = nextOldFiber;
            }
        
          // 2、处理新子节点遍历完的情况
            if (step.done) {
              deleteRemainingChildren(returnFiber, oldFiber);
              return resultingFirstChild;
            }
        
          // 3、处理旧子节点遍历完的情况
            if (oldFiber === null) {
              for (; !step.done; newIdx++, step = newChildren.next()) {
                const newFiber = createChild(returnFiber, step.value, lanes);
                if (newFiber === null) {
                  continue;
                }
                lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
                if (previousNewFiber === null) {
                  // TODO: Move out of the loop. This only happens for the first run.
                  resultingFirstChild = newFiber;
                } else {
                  previousNewFiber.sibling = newFiber;
                }
                previousNewFiber = newFiber;
              }
        
              return resultingFirstChild;
            }
        
          // 4、处理剩余的新旧子节点
            // Add all children to a key map for quick lookups.
            const existingChildren = mapRemainingChildren(oldFiber);
        
            // Keep scanning and use the map to restore deleted items as moves.
            for (; !step.done; newIdx++, step = newChildren.next()) {
              const newFiber = updateFromMap(
                existingChildren,
                returnFiber,
                newIdx,
                step.value,
                lanes,
              );
              if (newFiber !== null) {
                if (shouldTrackSideEffects) {
                  if (newFiber.alternate !== null) {
                    existingChildren.delete(
                      newFiber.key === null ? newIdx : newFiber.key,
                    );
                  }
                }
                lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
                if (previousNewFiber === null) {
                  resultingFirstChild = newFiber;
                } else {
                  previousNewFiber.sibling = newFiber;
                }
                previousNewFiber = newFiber;
              }
            }
        
          // 5、删除剩余的旧子节点
            if (shouldTrackSideEffects) {
              existingChildren.forEach(child => deleteChild(returnFiber, child));
            }
        
            return resultingFirstChild;
          }

        1-6 检查newChild为异步可迭代类型

            // 处理异步可迭代类型的子节点
            if (
              enableAsyncIterableChildren &&
              typeof newChild[ASYNC_ITERATOR] === 'function'
            ) {
              // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
              const firstChild = reconcileChildrenAsyncIteratable(
                returnFiber,
                currentFirstChild,
                newChild,
                lanes,
              );
              // currentDebugInfo = prevDebugInfo;
              return firstChild;
            }

        reconcileChildrenAsyncIteratable

        reconcileChildrenAsyncIteratable 函数主要用于处理异步可迭代的子节点。在 React 的协调过程中,当遇到异步可迭代的子节点时,该函数会对其进行处理,最终调用 reconcileChildrenIterator 函数完成子节点的协调工作。

        函数参数含义

        • returnFiber:类型为 Fiber,代表父 Fiber 节点,即当前处理的子节点所属的父节点。
        • currentFirstChild:类型为 Fiber | null,表示当前父 Fiber 节点的第一个子 Fiber 节点,如果没有子节点则为 null
        • newChildrenIterable:类型为 AsyncIterable<mixed>,是一个异步可迭代对象,包含了新的子节点数据。
        • lanes:类型为 Lanes,表示渲染优先级,用于确定此次更新的优先级。
          function reconcileChildrenAsyncIteratable(
            returnFiber: Fiber,
            currentFirstChild: Fiber | null,
            newChildrenIterable: AsyncIterable<mixed>,
            lanes: Lanes,
          ): Fiber | null {
          
            // 获取异步迭代器
            const newChildren = newChildrenIterable[ASYNC_ITERATOR]();
          
            if (newChildren == null) {
              throw new Error('An iterable object provided no iterator.');
            }
          
            // 创建同步迭代器
            const iterator: Iterator<mixed> = ({
              next(): IteratorResult<mixed, void> {
                return unwrapThenable(newChildren.next());
              },
            }: any);
          
            return reconcileChildrenIterator(
              returnFiber,
              currentFirstChild,
              iterator,// 同步迭代器
              lanes,
            );
          }

          1-7 检查newChild为Promise类型

              // 处理 Promise 类型的子节点
              if (typeof newChild.then === 'function') {
                const thenable: Thenable<any> = (newChild: any);
                // const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);
                  const firstChild = reconcileChildFibersImpl(
                    returnFiber,
                    currentFirstChild,
                    unwrapThenable(thenable),
                    lanes,
                  );
                  // currentDebugInfo = prevDebugInfo;
                  return firstChild;
              }

          1-8检查newChild.$$typeof为REACT_CONTEXT_TYPE

              // 处理 React Context 类型
                if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
                  const context: ReactContext<mixed> = (newChild: any);
                  return reconcileChildFibersImpl(
                    returnFiber,
                    currentFirstChild,
                    readContextDuringReconciliation(returnFiber, context, lanes),
                    lanes,
                  );
                }
          
                // throwOnInvalidObjectType(returnFiber, newChild);
              }

           

          工具函数之readContextDuringReconciliation

          readContextDuringReconciliation 函数是会根据当前渲染状态决定是否需要初始化上下文读取环境,然后调用 readContextForConsumer 实际读取上下文值并建立依赖关系。该函数确保在协调阶段安全地读取上下文,避免因环境未准备而导致的错误。

          function readContextDuringReconciliation<T>(
            consumer: Fiber,
            context: ReactContext<T>,
            renderLanes: Lanes,
          ): T {
          // 当 currentlyRenderingFiber 为 null 时,表示当前没有正在渲染的 Fiber,需要初始化上下文读取环境。
            if (currentlyRenderingFiber === null) {
              prepareToReadContext(consumer, renderLanes);
            }
            return readContextForConsumer(consumer, context);
          }

           

          工具函数之prepareToReadContext

          prepareToReadContext 函数是 React 渲染流程中的关键环节,用于为当前 Fiber 节点准备上下文读取环境。它主要完成以下工作:

          1. 设置当前渲染的 Fiber 节点。
          2. 重置上下文依赖链表。
          3. 处理上下文更新标记,确保依赖的上下文变化能触发组件重新渲染。
          function prepareToReadContext(
            workInProgress: Fiber,
            renderLanes: Lanes,
          ): void {
            currentlyRenderingFiber = workInProgress;
            lastContextDependency = null;
          
            const dependencies = workInProgress.dependencies;
            // 处理已有的上下文依赖
            if (dependencies !== null) {
              // 启用传播模式
              if (enableLazyContextPropagation) {
                // Reset the work-in-progress list
                dependencies.firstContext = null;
              } else {
                const firstContext = dependencies.firstContext;
                if (firstContext !== null) {
                  // 检查上下文是否有更新
                  if (includesSomeLane(dependencies.lanes, renderLanes)) {
                    // Context list has a pending update. Mark that this fiber performed work.
                    // 上下文有更新,标记当前 Fiber 执行了工作
                    markWorkInProgressReceivedUpdate();
                  }
                  // Reset the work-in-progress list
                  dependencies.firstContext = null;
                }
              }
            }
          }

          工具函数之readContextForConsumer

          readContextForConsumer 函数是 React 中用于读取上下文(Context)值的核心内部函数,主要用于类组件和函数组件中消费上下文。它会从当前上下文对象中获取最新值,并建立上下文依赖关系,确保当上下文值变化时,组件能正确触发重新渲染。

          function readContextForConsumer<C>(
            consumer: Fiber | null,
            context: ReactContext<C>,
          ): C {
            // 根据当前渲染器类型(主渲染器或辅助渲染器),从上下文对象(context)中获取对应的值。
            const value = isPrimaryRenderer
              ? context._currentValue
              : context._currentValue2;
          
            // 创建上下文依赖项
            const contextItem = {
              context: ((context: any): ReactContext<mixed>),
              memoizedValue: value,
              next: null,
            };
          
            // 当 lastContextDependency 为 null 时,说明组件首次读取上下文,创建新的依赖链表。
            if (lastContextDependency === null) {
              // 抛出错误:上下文只能在渲染阶段读取
              if (consumer === null) {
                throw new Error(
                  'Context can only be read while React is rendering. ' +
                    'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
                    'In function components, you can read it directly in the function body, but not ' +
                    'inside Hooks like useReducer() or useMemo().',
                );
              }
          
              // This is the first dependency for this component. Create a new list.
              // 初始化依赖链表
              lastContextDependency = contextItem;
              consumer.dependencies = {
                    lanes: NoLanes,
                    firstContext: contextItem,
                  };
              // 启用延迟上下文传播
              // if (enableLazyContextPropagation) {
              //   consumer.flags |= NeedsPropagation;
              // }
            } else {
              // 非首次依赖:将新的 contextItem 追加到链表末尾,形成链式结构(next 指针串联所有依赖项)。
              // Append a new context item.
              lastContextDependency = lastContextDependency.next = contextItem;
            }
            return value;
          }

          情况2:新节点为string类型 且不为空 或新节点为number类型或者bigint类型

          if (
                (typeof newChild === 'string' && newChild !== '') ||
                typeof newChild === 'number' ||
                typeof newChild === 'bigint'
              ) {
                return placeSingleChild(
                  reconcileSingleTextNode(
                    returnFiber,
                    currentFirstChild,
                    // $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint
                    '' + newChild,
                    lanes,
                  ),
                );
              }
          

          reconcileSingleTextNode 

          reconcileSingleTextNode 函数的主要功能是对单个文本节点进行协调(调和)操作。在 React 的协调算法中,该函数会对比现有的子 Fiber 节点和新的文本内容,尝试复用现有的文本 Fiber 节点,若无法复用则创建新的文本 Fiber 节点,以此确保 Fiber 树能够准确反映最新的文本内容。

          函数参数含义

          • returnFiber:类型为 Fiber,代表当前文本节点的父 Fiber 节点,即新文本节点要插入到的父节点。
          • currentFirstChild:类型为 Fiber | null,表示当前父 Fiber 节点的第一个子 Fiber 节点。若不存在子节点,该值为 null
          • textContent:类型为 string,是新的文本内容。
          • lanes:类型为 Lanes,代表渲染优先级车道,用于确定此次更新的优先级。
            function reconcileSingleTextNode(
              returnFiber: Fiber,//父节点
              currentFirstChild: Fiber | null,// 第一个子节点
              textContent: string,
              lanes: Lanes,
            ): Fiber {
              // 检查是否有可复用的文本 Fiber 节点
              if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
                deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
                // 复用节点
                const existing = useFiber(currentFirstChild, textContent);
                existing.return = returnFiber;
                return existing;
              }
              
              deleteRemainingChildren(returnFiber, currentFirstChild);
              const created = createFiberFromText(textContent, returnFiber.mode, lanes);
              created.return = returnFiber;
            
              return created;
            }

            createFiberFromText

            createFiberFromText 函数的主要功能是依据给定的文本内容、模式和优先级车道,创建一个代表文本节点的 Fiber 节点。在 React 的 Fiber 架构里,Fiber 节点是构建虚拟 DOM 树的基本单元,此函数专门用于创建文本类型的 Fiber 节点。

            函数参数含义:

            • content:类型为 string,代表要创建的文本节点的具体内容。
            • mode:类型为TypeOfMode,表示Fiber节点的模式,该模式会影响 Fiber节点在协调过程中的行为。
            • lanes:类型为 Lanes,表示渲染优先级,用于确定该 Fiber 节点的更新优先级。
              function createFiberFromText(
                content: string,
                mode: TypeOfMode,// 并发模式,传统模式
                lanes: Lanes,
              ): Fiber {
                // HostText常量6,表示该 Fiber 节点的类型为文本节点。
                // 文本节点通常没有 key,所以这里传入 null。key 一般用于在列表中唯一标识元素,帮助 React 识别哪些元素发生了变化。
                const fiber = createFiber(HostText, content, null, mode);
                fiber.lanes = lanes;
                return fiber;
              }

              情况3:其他

              return deleteRemainingChildren(returnFiber, currentFirstChild);

              deleteRemainingChildren

              用于删除从指定 Fiber 节点开始的所有剩余子 Fiber 节点。它会根据是否需要跟踪副作用来决定是否执行删除操作,若需要跟踪,则会逐个删除子节点。

              function deleteRemainingChildren(
                returnFiber: Fiber,// 父节点fiber
                currentFirstChild: Fiber | null,// 要删除的第一个子节点
              ): null {
                // 不需要跟踪副作用,,直接跳出
                if (!shouldTrackSideEffects) {
                  // Noop.
                  return null;
                }
                // 初始化 childToDelete 为 currentFirstChild,即从第一个子节点开始处理。
                let childToDelete = currentFirstChild;
                
                while (childToDelete !== null) {
                  
                  // 调用 deleteChild 函数来标记删除当前的子节点。
                  deleteChild(returnFiber, childToDelete);
              
                  // 将 childToDelete 更新为其下一个兄弟节点(通过 childToDelete.sibling),继续处理下一个子节点。
                  childToDelete = childToDelete.sibling;
                }
                return null;
              }

              deleteChild

              deleteChild 函数的主要功能是标记一个 Fiber 节点为待删除状态。在 React 的 Fiber 架构中,删除操作不会立即执行,而是先标记需要删除的节点,等到提交阶段(commit phase)再统一处理。这样做的好处是可以批量处理删除操作,减少对 DOM 的频繁修改,提高性能。

              function deleteChild(
                returnFiber: Fiber,// 父节点
                childToDelete: Fiber// 需要删除的子节点
              ): void {
              
                // shouldTrackSideEffects 是一个布尔值,用于控制是否需要跟踪副作用。副作用在 React 中通常指的是对 DOM 进行的插入、删除、更新等操作。如果不需要跟踪副作用,函数直接返回,不进行任何操作。这是一种优化机制,避免在不需要记录删除操作时进行额外的处理。
                if (!shouldTrackSideEffects) {
                  // Noop.
                  return;
                }
                
                // returnFiber.deletions 是一个数组,用于存储该父节点下需要删除的子 Fiber 节点。通过将需要删除的子节点存储在这个数组中,React 可以在后续的提交阶段一次性处理这些删除操作。
                const deletions = returnFiber.deletions;
                
                if (deletions === null) {
                  returnFiber.deletions = [childToDelete];
                  
                  // ChildDeletion 标记表示该父节点有子节点需要被删除。
                  returnFiber.flags |= ChildDeletion;
                } else {
                  // 将 childToDelete 添加到 deletions 数组中,以便后续统一处理。
                  deletions.push(childToDelete);
                }
              }

               工具函数之 placeSingleChild

              placeSingleChild 函数主要用于为单个新的 Fiber 节点标记插入副作用。在 React 的协调过程中,需要确定哪些 Fiber 节点需要进行插入操作,这个函数会根据特定条件判断新的 Fiber 节点是否需要被标记为插入,并设置相应的 flags

              
              function placeSingleChild(newFiber: Fiber): Fiber {
                // shouldTrackSideEffects 说明是否需要跟踪 (挂载时为false, 更新时为true)
                // 副作用一般指的是会对外部状态产生影响的操作,像插入、删除、更新 DOM 节点等。
               // newFiber.alternate为null ,说明newFiber是新创建的
                if (shouldTrackSideEffects && newFiber.alternate === null) {
                  
                  newFiber.flags |= Placement | PlacementDEV;// 代表插入
                }
                return newFiber;
              }

              工具函数之 useFiber

              基于已有的 Fiber 节点创建一个新的 workInProgress(进行中的工作)Fiber 节点。workInProgress 用于表示当前正在处理的 Fiber 树,通过复用旧的 Fiber 节点可以提高性能。这个函数接收一个旧的 Fiber 节点和新的 props,然后返回一个新的 workInProgress Fiber 节点,并且会重置该节点的索引和兄弟节点信息。

              function useFiber(fiber: Fiber, pendingProps: mixed): Fiber {
                const clone = createWorkInProgress(fiber, pendingProps);
                clone.index = 0;
                clone.sibling = null;
                return clone;
              }

              工具函数之 createWorkInProgress

              createWorkInProgress用于创建或复用一个 workInProgress(进行中的工作)Fiber 节点。在 React 的渲染流程中,为了实现可中断的渲染和双缓存机制,会使用两个 Fiber 树:当前渲染的 Fiber 树(current)和正在构建的 Fiber 树(workInProgress)。这个函数的作用就是根据当前的 Fiber 节点(current)和新的待处理属性(pendingProps),创建或更新 workInProgress 节点。

              参数说明:

              • current: Fiber:当前正在渲染的 Fiber 节点。
              • pendingProps: any:新的待处理属性,用于更新 workInProgress 节点。
               function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
                let workInProgress = current.alternate;
              
              // 如果 workInProgress 为 null,说明还没有对应的进行中的工作节点,需要创建一个新的
                if (workInProgress === null) {
                  // 创建新的 workInProgress 节点
                  workInProgress = createFiber(
                    current.tag,// 当前节点的类型标签(tag)
                    pendingProps,// 待处理的props
                    current.key,
                    current.mode,
                  );
              
                  // 复制当前节点的 elementType、type 和 stateNode 到新节点。
                  workInProgress.elementType = current.elementType;
                  workInProgress.type = current.type;
                  workInProgress.stateNode = current.stateNode;
              
                  // 建立 workInProgress 和 current 之间的双向引用,即 workInProgress.alternate 指向 current,current.alternate 指向 workInProgress。
                  workInProgress.alternate = current;
                  current.alternate = workInProgress;
                } else {
                  // 复用已有的 workInProgress 节点并更新属性
                  
                  workInProgress.pendingProps = pendingProps;
                  // Needed because Blocks store data on type.
                  workInProgress.type = current.type;
              
                  // We already have an alternate.
                  // Reset the effect tag.
                  workInProgress.flags = NoFlags;
              
                  // The effects are no longer valid.
                  workInProgress.subtreeFlags = NoFlags;
                  workInProgress.deletions = null;
                }
                 
                // 复制部分属性到 workInProgress 节点
                workInProgress.flags = current.flags & StaticMask;
                workInProgress.childLanes = current.childLanes;
                workInProgress.lanes = current.lanes;
              
                workInProgress.child = current.child;
                workInProgress.memoizedProps = current.memoizedProps;// 上一次的渲染属性
                workInProgress.memoizedState = current.memoizedState;// 上一次渲染状态
                workInProgress.updateQueue = current.updateQueue;// 更新队列
              
              
                const currentDependencies = current.dependencies;
              
                 // 对于依赖项,进行浅复制,避免共享引用。
                workInProgress.dependencies =
                  currentDependencies === null
                    ? null
                    :  {
                          lanes: currentDependencies.lanes,
                          firstContext: currentDependencies.firstContext,
                        };
              
                // These will be overridden during the parent's reconciliation
                workInProgress.sibling = current.sibling;
                workInProgress.index = current.index;
                workInProgress.ref = current.ref;
                workInProgress.refCleanup = current.refCleanup;
              
                return workInProgress;
              }

              工具函数之 coerceRef

              coerceRef 函数的主要作用是将 ReactElement(即 React 元素)的 ref 属性赋值给对应的 Fiber 节点(workInProgress)。在 React 的协调过程中,Fiber 节点是协调算法的工作单元,用于表示组件树中的一个节点,而 ref 属性通常用于获取 DOM 节点或组件实例的引用。

              function coerceRef(workInProgress: Fiber, element: ReactElement): void {
               // 获取react元素的ref属性
                const refProp = element.props.ref;
                // should always read the ref from the prop.
                // 将refProp赋给当前fiber
                workInProgress.ref = refProp !== undefined ? refProp : null;
              }

              工具函数之 placeChild

              placeChild 函数主要负责确定新 Fiber 节点在 Fiber 树中的位置,并根据情况标记该节点是需要移动、插入还是保持原位,同时返回更新后的 lastPlacedIndex 值。lastPlacedIndex 用于记录上一个已放置节点的索引,以此来判断当前节点是否需要移动。

              函数参数含义

              • newFiber:类型为 Fiber,代表新创建或复用的 Fiber 节点,需要为其确定在 Fiber 树中的位置。
              • lastPlacedIndex:类型为 number,表示上一个已放置节点的索引,用于判断当前节点是否需要移动。
              • newIndex:类型为 number,是新 Fiber 节点在新子节点数组中的索引。
              function placeChild(
                newFiber: Fiber,
                lastPlacedIndex: number,
                newIndex: number,
              ): number {
                // 设置新 Fiber 节点的索引
                newFiber.index = newIndex;
              
                // 处理不需要跟踪副作用的情况 (初始化时)
                if (!shouldTrackSideEffects) {
                  newFiber.flags |= Forked;
                  return lastPlacedIndex;
                }
              
                // 获取旧 Fiber 节点
                const current = newFiber.alternate;
                
                if (current !== null) {
                  const oldIndex = current.index;
                  if (oldIndex < lastPlacedIndex) {
                    // 说明需要移动
                    newFiber.flags |= Placement | PlacementDEV;
                    return lastPlacedIndex;
                  } else {
                    // This item can stay in place.
                    return oldIndex;
                  }
                } else {
                   // 处理不存在旧 Fiber 节点的情况
                  // This is an insertion.
                  newFiber.flags |= Placement | PlacementDEV;
                  return lastPlacedIndex;
                }
              }

              工具函数之 createChild

              createChild 函数用于根据不同类型的 newChild 创建对应的 Fiber 节点,并将其连接到父 Fiber(returnFiber)。它是 React 协调过程中的核心函数之一,负责处理各种类型的 React 元素,包括文本节点、普通元素、Portal、延迟加载组件等。

              function createChild(
                returnFiber: Fiber,
                newChild: any,
                lanes: Lanes,
              ): Fiber | null {
                // 处理原始类型(字符串、数字、大整数)
                if (
                  (typeof newChild === 'string' && newChild !== '') ||
                  typeof newChild === 'number' ||
                  typeof newChild === 'bigint'
                ) {
                  const created = createFiberFromText(
                    '' + newChild,
                    returnFiber.mode,
                    lanes,
                  );
                  created.return = returnFiber;
                  return created;
                }
              
                // 处理对象类型
                if (typeof newChild === 'object' && newChild !== null) {
                  switch (newChild.$$typeof) {
                    case REACT_ELEMENT_TYPE: {
                      const created = createFiberFromElement(
                        newChild,
                        returnFiber.mode,
                        lanes,
                      );
                      coerceRef(created, newChild);
                      created.return = returnFiber;
                      return created;
                    }
                    case REACT_PORTAL_TYPE: {
                      const created = createFiberFromPortal(
                        newChild,
                        returnFiber.mode,
                        lanes,
                      );
                      created.return = returnFiber;
              
                      return created;
                    }
                    case REACT_LAZY_TYPE: {
                      // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
                      let resolvedChild;
              
                      const payload = newChild._payload;
                      const init = newChild._init;
                      resolvedChild = init(payload);
                    
                      const created = createChild(returnFiber, resolvedChild, lanes);
                      // currentDebugInfo = prevDebugInfo;
                      return created;
                    }
                  }
              
                  if (
                    isArray(newChild) ||
                    getIteratorFn(newChild) ||
                    (enableAsyncIterableChildren &&
                      typeof newChild[ASYNC_ITERATOR] === 'function')
                  ) {
                    const created = createFiberFromFragment(
                      newChild,
                      returnFiber.mode,
                      lanes,
                      null,
                    );
                    created.return = returnFiber;
                    return created;
                  }
              
                  // Usable node types
                  //
                  // Unwrap the inner value and recursively call this function again.
                  if (typeof newChild.then === 'function') {
                    const thenable: Thenable<any> = (newChild: any);
                    // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
                    const created = createChild(
                      returnFiber,
                      unwrapThenable(thenable),
                      lanes,
                    );
                    // currentDebugInfo = prevDebugInfo;
                    return created;
                  }
              
                  if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
                    const context: ReactContext<mixed> = (newChild: any);
                    return createChild(
                      returnFiber,
                      readContextDuringReconciliation(returnFiber, context, lanes),
                      lanes,
                    );
                  }
              
                  // throwOnInvalidObjectType(returnFiber, newChild);
                }
              
                return null;
              }

              工具函数之 updateSlot

              updateSlot 函数主要用于根据新的子元素(newChild)和旧 fiber(oldFiber)来更新父 fiber(returnFiber)的插槽内容。它会根据子元素的类型(文本、对象、数组、可迭代对象、Promise 等)进行不同的处理,以实现对纤维的更新或返回 null(当键不匹配或无法处理子元素类型时)。

              function updateSlot(
                returnFiber: Fiber,
                oldFiber: Fiber | null,
                newChild: any,
                lanes: Lanes,
              ): Fiber | null {
                // Update the fiber if the keys match, otherwise return null.
                const key = oldFiber !== null ? oldFiber.key : null;
              
                if (
                  (typeof newChild === 'string' && newChild !== '') ||
                  typeof newChild === 'number' ||
                  typeof newChild === 'bigint'
                ) {
                  if (key !== null) {
                    return null;
                  }
                  return updateTextNode(
                    returnFiber,
                    oldFiber,
                    '' + newChild,
                    lanes,
                  );
                }
              
                if (typeof newChild === 'object' && newChild !== null) {
                  switch (newChild.$$typeof) {
                    case REACT_ELEMENT_TYPE: {
                      if (newChild.key === key) {
                        const updated = updateElement(
                          returnFiber,
                          oldFiber,
                          newChild,
                          lanes,
                        );
                      
                        return updated;
                      } else {
                        return null;
                      }
                    }
                    case REACT_PORTAL_TYPE: {
                      if (newChild.key === key) {
                        return updatePortal(returnFiber, oldFiber, newChild, lanes);
                      } else {
                        return null;
                      }
                    }
                    case REACT_LAZY_TYPE: {
                    
                      let resolvedChild;
              
                      const payload = newChild._payload;
                      const init = newChild._init;
                      resolvedChild = init(payload);
                    
                      const updated = updateSlot(
                        returnFiber,
                        oldFiber,
                        resolvedChild,
                        lanes,
                      );
              
                      return updated;
                    }
                  }
              
                  if (
                    isArray(newChild) ||
                    getIteratorFn(newChild) ||
                    (enableAsyncIterableChildren &&
                      typeof newChild[ASYNC_ITERATOR] === 'function')
                  ) {
                    if (key !== null) {
                      return null;
                    }
              
              
                    const updated = updateFragment(
                      returnFiber,
                      oldFiber,
                      newChild,
                      lanes,
                      null,
                    );
                   
                    return updated;
                  }
              
                  // Usable node types
                  //
                  // Unwrap the inner value and recursively call this function again.
                  if (typeof newChild.then === 'function') {
                    const thenable: Thenable<any> = (newChild: any);
                   
                    const updated = updateSlot(
                      returnFiber,
                      oldFiber,
                      unwrapThenable(thenable),
                      lanes,
                    );
                   
                    return updated;
                  }
              
                  if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
                    const context: ReactContext<mixed> = (newChild: any);
                    return updateSlot(
                      returnFiber,
                      oldFiber,
                      readContextDuringReconciliation(returnFiber, context, lanes),
                      lanes,
                    );
                  }
              
                  throwOnInvalidObjectType(returnFiber, newChild);
                }
              
                return null;
              }

              工具函数之 mapRemainingChildren

              创建一个新的 Map 对象 existingChildren,用于存储子 Fiber 节点。Map 的键可以是字符串类型(当子 Fiber 节点有 key 属性时)或者数字类型(当子 Fiber 节点没有 key 属性时,使用其 index 作为键),值为对应的 Fiber 节点。

              function mapRemainingChildren(
                currentFirstChild: Fiber,//当前父 Fiber 节点的第一个子 Fiber 节点。
              ): Map<string | number, Fiber> {
                
                const existingChildren: Map<string | number, Fiber> = new Map();
              
                let existingChild: null | Fiber = currentFirstChild;
                
                while (existingChild !== null) {
                  if (existingChild.key !== null) {
                    existingChildren.set(existingChild.key, existingChild);
                  } else {
                    // 用索引作为key
                    existingChildren.set(existingChild.index, existingChild);
                  }
              
                  // 处理下一个兄弟节点
                  existingChild = existingChild.sibling;
                }
              
                //  返回存储子 Fiber 节点的 Map
                return existingChildren;
              }

              工具函数之 updateFromMap

              updateFromMap 函数主要用于处理以 Map 结构存储的现有子节点existingChildren)与新子节点(newChild)的匹配和更新逻辑。它会根据子节点的类型(文本、元素、Portal、延迟加载组件等),从 Map 中查找匹配的旧纤维(Fiber),并执行更新、复用或创建操作。

              function updateFromMap(
                existingChildren: Map<string | number, Fiber>,
                returnFiber: Fiber,
                newIdx: number,
                newChild: any,
                lanes: Lanes,
              ): Fiber | null {
              
                // 处理普通类型的
                if (
                  (typeof newChild === 'string' && newChild !== '') ||
                  typeof newChild === 'number' ||
                  typeof newChild === 'bigint'
                ) {
                  const matchedFiber = existingChildren.get(newIdx) || null;
                  return updateTextNode(
                    returnFiber,
                    matchedFiber,
                    '' + newChild,
                    lanes,
                  );
                }
              
                // 处理对象类型
                if (typeof newChild === 'object' && newChild !== null) {
                  switch (newChild.$$typeof) {
                    case REACT_ELEMENT_TYPE: {
                      const matchedFiber =
                        existingChildren.get(
                          newChild.key === null ? newIdx : newChild.key,
                        ) || null;
                      // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
                      const updated = updateElement(
                        returnFiber,
                        matchedFiber,
                        newChild,
                        lanes,
                      );
                      // currentDebugInfo = prevDebugInfo;
                      return updated;
                    }
                    case REACT_PORTAL_TYPE: {
                      const matchedFiber =
                        existingChildren.get(
                          newChild.key === null ? newIdx : newChild.key,
                        ) || null;
                      return updatePortal(returnFiber, matchedFiber, newChild, lanes);
                    }
                    case REACT_LAZY_TYPE: {
                      // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
                      let resolvedChild;
               
                      const payload = newChild._payload;
                      const init = newChild._init;
                      resolvedChild = init(payload);
                    
                      const updated = updateFromMap(
                        existingChildren,
                        returnFiber,
                        newIdx,
                        resolvedChild,
                        lanes,
                      );
                      // currentDebugInfo = prevDebugInfo;
                      return updated;
                    }
                  }
              
                  if (
                    isArray(newChild) ||
                    getIteratorFn(newChild) ||
                    (enableAsyncIterableChildren &&
                      typeof newChild[ASYNC_ITERATOR] === 'function')
                  ) {
                    const matchedFiber = existingChildren.get(newIdx) || null;
                    // const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
                    const updated = updateFragment(
                      returnFiber,
                      matchedFiber,
                      newChild,
                      lanes,
                      null,
                    );
                    // currentDebugInfo = prevDebugInfo;
                    return updated;
                  }
              
                  // Usable node types
                  //
                  // Unwrap the inner value and recursively call this function again.
                  if (typeof newChild.then === 'function') {
                    const thenable: Thenable<any> = (newChild: any);
                    // const prevDebugInfo = pushDebugInfo((thenable: any)._debugInfo);
                    const updated = updateFromMap(
                      existingChildren,
                      returnFiber,
                      newIdx,
                      unwrapThenable(thenable),
                      lanes,
                    );
                    // currentDebugInfo = prevDebugInfo;
                    return updated;
                  }
              
                  if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
                    const context: ReactContext<mixed> = (newChild: any);
                    return updateFromMap(
                      existingChildren,
                      returnFiber,
                      newIdx,
                      readContextDuringReconciliation(returnFiber, context, lanes),
                      lanes,
                    );
                  }
              
                  // throwOnInvalidObjectType(returnFiber, newChild);
                }
              
                return null;
              }

               

              工具函数之 updateElement

              updateElement 函数用于处理 React 元素的更新或创建操作。它会根据元素类型、当前纤维状态以及新旧元素的匹配情况,决定是复用现有 fiber(useFiber)还是创建新 fiber(createFiberFromElement)。该函数是 React 协调过程的核心部分,负责处理普通元素和 Fragment 类型的更新逻辑。

              function updateElement(
                returnFiber: Fiber,
                current: Fiber | null,
                element: ReactElement,
                lanes: Lanes,
              ): Fiber {
                const elementType = element.type;
                if (elementType === REACT_FRAGMENT_TYPE) {
                  const updated = updateFragment(
                    returnFiber,
                    current,
                    element.props.children,
                    lanes,
                    element.key,
                  );
                  // validateFragmentProps(element, updated, returnFiber);
                  return updated;
                }
                if (current !== null) {
                  if (
                    current.elementType === elementType ||
                    (typeof elementType === 'object' &&
                      elementType !== null &&
                      elementType.$$typeof === REACT_LAZY_TYPE &&
                      resolveLazy(elementType) === current.type)
                  ) {
                    // Move based on index
                    const existing = useFiber(current, element.props);
                    coerceRef(existing, element);
                    existing.return = returnFiber;
              
                    return existing;
                  }
                }
                // Insert
                const created = createFiberFromElement(element, returnFiber.mode, lanes);
                coerceRef(created, element);
                created.return = returnFiber;
              
                return created;
              }

              工具函数之 updateFragement

              function updateFragment(
                returnFiber: Fiber,
                current: Fiber | null,
                fragment: Iterable<React$Node>,
                lanes: Lanes,
                key: null | string,
              ): Fiber {
                if (current === null || current.tag !== Fragment) {
                  // Insert
                  const created = createFiberFromFragment(
                    fragment,
                    returnFiber.mode,
                    lanes,
                    key,
                  );
                  created.return = returnFiber;
              
                  return created;
                } else {
                  // Update
                  const existing = useFiber(current, fragment);
                  existing.return = returnFiber;
              
                  return existing;
                }
              }

              工具函数之 updateTextNode

              updateTextNode 函数用于处理文本节点的更新或创建操作。它会根据当前是否存在旧 fiber(current)以及旧 fiber 的类型,决定是复用现有 fiber 还是创建新 fiber。

              function updateTextNode(
                returnFiber: Fiber,
                current: Fiber | null,
                textContent: string,
                lanes: Lanes,
              ) {
                if (current === null || current.tag !== HostText) {
                  // Insert
                  const created = createFiberFromText(textContent, returnFiber.mode, lanes);
                  created.return = returnFiber;
                  return created;
                } else {
                  // Update
                  const existing = useFiber(current, textContent);
                  existing.return = returnFiber;
                  return existing;
                }
              }

              全局变量

              export const FunctionComponent = 0;
              export const ClassComponent = 1;
              export const HostRoot = 3; // Root of a host tree. Could be nested inside another node.
              export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
              export const HostComponent = 5;
              export const HostText = 6;
              export const Fragment = 7;
              export const Mode = 8;
              export const ContextConsumer = 9;
              export const ContextProvider = 10;
              export const ForwardRef = 11;
              export const Profiler = 12;
              export const SuspenseComponent = 13;
              export const MemoComponent = 14;
              export const SimpleMemoComponent = 15;
              export const LazyComponent = 16;
              export const IncompleteClassComponent = 17;
              export const DehydratedFragment = 18;
              export const SuspenseListComponent = 19;
              export const ScopeComponent = 21;
              export const OffscreenComponent = 22;
              export const LegacyHiddenComponent = 23;
              export const CacheComponent = 24;
              export const TracingMarkerComponent = 25;
              export const HostHoistable = 26;
              export const HostSingleton = 27;
              export const IncompleteFunctionComponent = 28;
              export const Throw = 29;
              

              fiber树结构

              <div>
                <p></p>
                <div></div>
                <span></span>
              </div>

              react支持浏览器的内置组件

              React DOM 组件 – React 中文文档

              1、通用组件(如 <div>)

              这些组件在 React 中可以使用 React 特有的属性,如 ref 与 dangerouslySetInnerHTML。

              2、表单组件

              • <input>
              • <select>
              • <textarea>

              将 value 作为 prop 传递给这些组件会将其变为 受控组件。

              3、资源和mata组件

              • <link>
              • <meta>
              • <script>
              • <style>
              • <title>

              4、所有html组件

              <aside>
              <audio>
              <b>
              <base>
              <bdi>
              <bdo>
              <blockquote>
              <body>
              <br>等等

              5、所有svg组件

               

              单例宿主组件(HostSingleton

              一、定义

              单例宿主组件指的是在整个 React 应用中只能存在一个实例的宿主组件。宿主组件一般代表原生 DOM 元素,像 <div><span> 这类。单例宿主组件可能和特定的 DOM 元素或者系统资源有关,这些资源在应用里仅允许有一个实例。

              二、用途

              • 资源管理:在某些场景下,应用仅需一个特定的 DOM 元素或者系统资源,例如全局的模态框、全局的通知栏等。使用单例宿主组件可以保证这些资源仅被创建一次,避免资源的重复创建与浪费。
              • 状态管理:单例宿主组件可以用来管理全局状态。因为只有一个实例,所以状态的管理会更加简单和可控。

               

              可提升的宿主组件(HostHoistable)

              一、定义

              可提升的宿主组件是指那些可以被提升到更高级别 DOM 树中的宿主组件。提升操作通常是为了优化渲染性能,减少不必要的 DOM 操作。

              二、用途

              • 性能优化:当某些宿主组件的渲染频率较高或者对性能影响较大时,将它们提升到更高级别的 DOM 树中,可以减少这些组件的重新渲染次数,从而提升应用的性能。
              • 减少 DOM 操作:通过提升组件,可以避免在每次渲染时都创建和销毁这些组件对应的 DOM 元素,减少 DOM 操作的开销。

              网站公告

              今日签到

              点亮在社区的每一天
              去签到