感謝 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'));/複製代碼
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
是 傳入的組件,container
DOM節點容器,callback是回調函數。ReactDOM.render文檔。數據結構
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複製代碼
function legacyCreateRootFromDOMContainer(
container: DOMContainer,
forceHydrate: boolean,
): Root {
const isConcurrent = false;
// 調用ReactRoot函數 建立ReactRoot, shouldHydrate是SSR相關,不用管
return new ReactRoot(container, isConcurrent, shouldHydrate);
}複製代碼
function ReactRoot(
container: DOMContainer,
isConcurrent: boolean,
hydrate: boolean,
) {
// 這個 root 指的是 FiberRoot
const root = createContainer(container, isConcurrent, hydrate);
this._internalRoot = root;
}複製代碼
調用createContainer 建立FiberRoot,下面咱們將會說到FiberRoot 對象
export function createContainer(
containerInfo: Container,
isConcurrent: boolean,
hydrate: boolean,
): OpaqueRoot {
return createFiberRoot(containerInfo, isConcurrent, hydrate);
}複製代碼
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')
)複製代碼
以上圖片中只有FiberRoot的部分屬性,想了解更多,能夠查看FiberRoot的數據結構!!
更多內容:
react解析: React.createElement(一)
參考:
Jokcy 的 《React 源碼解析》: react.jokcy.me/
ps: 順便推一下本身的我的公衆號:Yopai,有興趣的能夠關注,每週不按期更新,分享能夠增長世界的快樂