react解析 render的FiberRoot(三)

react解析 render的FiberRoot

感謝 yck: 剖析 React 源碼解析,本篇文章是在讀完他的文章的基礎上,將他的文章進行拆解和加工,加入我本身的一下理解和例子,便於你們理解。以爲yck寫的真的很棒 。React 版本爲 16.8.6,關於源碼的閱讀,能夠移步到yck react源碼解析html

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

下面將會說到 ReactDOM.render 在ReactDOM中的調用流程,實際就是分析下面代碼:git

ReactDOM.render(<APP />, document.getElementById('app'))複製代碼

實際代碼:github

ReactDOM.render(React.createElement(APP, null), document.getElementById('app'));/複製代碼

render 函數

yck: ReactDOM 源碼 702行 renderapi

ReactDOM.render實際調用的就是下面的代碼bash

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行 legacyRenderSubtreeIntoContainerapp

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屬性。dom

// 查看_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 源碼 276行 createContainer

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

yck: ReactDOM 源碼 168行 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,有興趣的能夠關注,每週不按期更新,分享能夠增長世界的快樂

相關文章
相關標籤/搜索