Skip to content

react解析 render的FiberRoot(三) #9

Open
@HerryLo

Description

@HerryLo
Member

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,有兴趣的可以关注,每周不定期更新,分享可以增加世界的快乐

Activity

self-assigned this
on Aug 10, 2019
changed the title [-]react解析 render的FiberRoot[/-] [+]react解析 render的FiberRoot(三)[/+] on Aug 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @HerryLo

      Issue actions

        react解析 render的FiberRoot(三) · Issue #9 · AttemptWeb/Record