zoukankan      html  css  js  c++  java
  • react解析: render的FiberRoot(三)

    react解析: render的FiberRoot(三)

    感谢 yck: 剖析 React 源码解析,本篇文章是在读完他的文章的基础上,将他的文章进行拆解和加工,加入我自己的一下理解和例子,便于大家理解。觉得yck写的真的很棒 。React 版本为 16.8.6,关于源码的阅读,可以移步到yck react源码解析

    本文永久有效链接: react解析 render的FiberRoot(三)

    下面将会说到 ReactDOM.render 在ReactDOM中的调用流程,实际就是分析下面代码:

    ReactDOM.render(<APP />, document.getElementById('app'))

    实际代码:

    ReactDOM.render(React.createElement(APP, null), document.getElementById('app'));

    render 函数

    yck: ReactDOM 源码 702行 render

    ReactDOM.render实际调用的就是下面的代码

    render(
        element: React$Element<any>,
        container: DOMContainer,
        callback: ?Function,
      ) {
        // 注意下 forceHydrate 参数,为 true 时是服务端渲染
        // 客户端调用 render 函数的话这个值永远为 false
        return legacyRenderSubtreeIntoContainer(
          null,
          element,
          container,
          false,
          callback,
        );
      }

    render函数中的参数element是 传入的组件,containerDOM节点容器,callback是回调函数。ReactDOM.render文档

    legacyRenderSubtreeIntoContainer 函数

    yck: ReactDOM 源码 554行 legacyRenderSubtreeIntoContainer

    function legacyRenderSubtreeIntoContainer(
      parentComponent: ?React$Component<any, any>,
      children: ReactNodeList,
      container: DOMContainer,
      forceHydrate: boolean,
      callback: ?Function,
    ) {
        // 初始化时,container 肯定没有 _reactRootContainer属性
        let root: Root = (container._reactRootContainer: any);
        if (!root) {
            root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
                container,    // DOM容器节点
                forceHydrate, // 为false
            );
            // 暂时只说root不存在时,reactRoot的创建
        }
    }

    container表示DOM元素节点容器, 在上面的代码中会创建一个ReactRoot,然后将它挂载在container容器上, container._reactRootContainer就是挂载的ReactRoot属性。

    // 查看_reactRootContainer
    document.getElementById('app')._reactRootContainer

    创建FiberRoot核心函数

    yck: ReactDOM 源码 504行 legacyCreateRootFromDOMContainer

    function legacyCreateRootFromDOMContainer(
      container: DOMContainer,
      forceHydrate: boolean,
    ): Root {
      const isConcurrent = false;
      // 调用ReactRoot函数 创建ReactRoot, shouldHydrate是SSR相关,不用管
      return new ReactRoot(container, isConcurrent, shouldHydrate);
    }

    yck: ReactDOM 源码 368行 ReactRoot

    function ReactRoot(
      container: DOMContainer,
      isConcurrent: boolean,
      hydrate: boolean,
    ) {
      // 这个 root 指的是 FiberRoot
      const root = createContainer(container, isConcurrent, hydrate);
      this._internalRoot = root;
    }

    调用createContainer 创建FiberRoot,下面我们将会说到FiberRoot 对象

    FiberRoot

    yck: ReactDOM 源码 368行 createContainer

    export function createContainer(
      containerInfo: Container,
      isConcurrent: boolean,
      hydrate: boolean,
    ): OpaqueRoot {
      return createFiberRoot(containerInfo, isConcurrent, hydrate);
    }

    yck: ReactDOM 源码 368行 createFiberRoot

    function createFiberRoot(
      containerInfo: any,
      isConcurrent: boolean,
      hydrate: boolean,
    ): FiberRoot {
      const root: FiberRoot = (new FiberRootNode(containerInfo, hydrate): any);
      const uninitializedFiber = createHostRootFiber(isConcurrent);
      root.current = uninitializedFiber;
      uninitializedFiber.stateNode = root;
    
      return root;
    }

    createFiberRoot函数中,首先创建了一个root: FiberRoot,然后又创建了一个uninitializedFiber: RootFiber,它们两者还是相互引用。

    // 查看 FiberRoot 对象
    document.getElementById('app')._reactRootContainer._internalRoot
    

    我们下面顺便说一下FiberRoot 和 RootFiber的关系,同时拿出几个必须要要了解的属性解释一下。

    ReactDom.render(
      ()=> (
        <div>
          <div></div>
          <div></div>
        </div>
      ), 
      document.querySelector('#root')
    )

    img

    以上图片中只有FiberRoot的部分属性,想了解更多,可以查看FiberRoot的数据结构哦!!

    更多内容:

    react解析: React.createElement(一)

    react解析: React.Children(二)

    参考:

    yck: 剖剖析 React 源码

    Jokcy 的 《React 源码解析》: react.jokcy.me/

    ps: 顺便推一下自己的个人公众号:Yopai,有兴趣的可以关注,每周不定期更新,分享可以增加世界的快乐

  • 相关阅读:
    反射/元类/项目的生命周期
    面向对象高级
    面向对象之封装/鸭子类型
    面向对象之继承
    面向对象1
    包/logging模块/hashlib模块/openpyxl模块/深浅拷贝
    python 几行代码实现自动回复功能
    python crypto rsa 加密运用
    pytohn 单下划线与双下划线的区别
    python 线程小练习
  • 原文地址:https://www.cnblogs.com/liuheng/p/11331398.html
Copyright © 2011-2022 走看看