摘要:系列文章源碼分析第一篇源碼分析第二篇同步模式源碼分析第三篇異步狀態(tài)源碼分析第四篇?dú)w納總結(jié)前言是在版本中的大更新,利用了閑余時(shí)間看了一些源碼,做個(gè)小記錄流程圖源碼分析先由編譯,調(diào)用,入?yún)椋蛴〕鰜?lái)可以看到,,分別代表著元素原生元素,回調(diào)函數(shù)
系列文章
React Fiber源碼分析 第一篇
React Fiber源碼分析 第二篇(同步模式)
React Fiber源碼分析 第三篇(異步狀態(tài))
React Fiber源碼分析 第四篇(歸納總結(jié))
React Fiber是React在V16版本中的大更新,利用了閑余時(shí)間看了一些源碼,做個(gè)小記錄~
流程圖 源碼分析先由babel編譯, 調(diào)用reactDOM.render,入?yún)?strong>element, container, callback, 打印出來(lái)可以看到element,container,callback分別代表著react元素、DOM原生元素,回調(diào)函數(shù)
1.render實(shí)際上調(diào)用的是legacyRenderSubtreeIntoContainer函數(shù)
render: function (element, container, callback) { return legacyRenderSubtreeIntoContainer(null, element, container, false, callback); }
2.legacyRenderSubtreeIntoContainer 這個(gè)函數(shù), 實(shí)際上是初始化了root, 并調(diào)用了root.render方法, 而root是由legacyCreateRootFromDOMContainer函數(shù)返回的
function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) { var root = container._reactRootContainer; if (!root) { // 初始化root root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);// Initial mount should not be batched. unbatchedUpdates(function () { if (parentComponent != null) { root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback); } else { // 調(diào)用root的render方法 root.render(children, callback); } }); } else { ...... } }
3.從代碼中看出, legacyCreateRootFromDOMContainer執(zhí)行了兩個(gè)操作, 一個(gè)是清除掉所有的子元素, 另外一個(gè)則是返回了一個(gè) ReactRoot實(shí)例, 這里需要注意一點(diǎn), root默認(rèn)是同步更新的, 即isAsync 默認(rèn)為false
function legacyCreateRootFromDOMContainer(container, forceHydrate) { ...// 清除所有子元素 if (!shouldHydrate) { var warned = false; var rootSibling = void 0; while (rootSibling = container.lastChild) { { if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) { warned = true; } } container.removeChild(rootSibling); } }// 默認(rèn)為同步狀態(tài) var isAsync = false; return new ReactRoot(container, isAsync, shouldHydrate); }
4.從ReactRoot中, 我們把createContainer返回值賦給了 實(shí)例的_internalRoot, 往下看createContainer
function ReactRoot(container, isAsync, hydrate) { var root = createContainer(container, isAsync, hydrate); this._internalRoot = root; }
5.從createContainer看出, createContainer實(shí)際上是直接返回了createFiberRoot, 而createFiberRoot則是通過(guò)createHostRootFiber函數(shù)的返回值uninitializedFiber,并將其賦值在root對(duì)象的current上, 這里需要注意一個(gè)點(diǎn)就是,uninitializedFiber的stateNode的值是root, 即他們互相引用
function createContainer(containerInfo, isAsync, hydrate) { return createFiberRoot(containerInfo, isAsync, hydrate); } function createFiberRoot(containerInfo, isAsync, hydrate) { // 創(chuàng)建hostRoot并賦值給uninitiallizedFiber var uninitializedFiber = createHostRootFiber(isAsync); // 互相引用 var root = void 0; root = { current: uninitializedFiber, ... }; uninitializedFiber.stateNode = root;
6.最后是返回了一個(gè)fiberNode的實(shí)例, 在這里我們可以看到mode這個(gè)字段, 由于在一開(kāi)始就將isAsync初始化為false, 所以mode實(shí)際上就代表了同步
在這里, 整理一下各個(gè)實(shí)例的關(guān)系,
root為ReactRoot實(shí)例,
root._internalRoot 即為fiberRoot實(shí)例,
root._internalRoot.current即為Fiber實(shí)例,
root._internalRoot.current.stateNode = root._internalRoot
function createHostRootFiber(isAsync) { var mode = isAsync ? AsyncMode | StrictMode : NoContext; return createFiber(HostRoot, null, null, mode); } var createFiber = function (tag, pendingProps, key, mode) { return new FiberNode(tag, pendingProps, key, mode); }; function FiberNode(tag, pendingProps, key, mode) { // Instance this.tag = tag; this.key = key; this.type = null; this.stateNode = null; // Fiber this.return = null; this.child = null; this.sibling = null; this.index = 0; ... }
7.初始化完成, 接下來(lái)就是root.render執(zhí)行了, 在這里, 先暫時(shí)忽略ReactWork, 把work._onCommit當(dāng)成一個(gè)回調(diào)函數(shù)即可, 可以看到, root即FiberRoot實(shí)例被當(dāng)成參數(shù)傳入了updateContsainer里面, 往下看updateContainer
ReactRoot.prototype.render = function (children, callback) { var root = this._internalRoot; var work = new ReactWork(); callback = callback === undefined ? null : callback; if (callback !== null) { work.then(callback); } updateContainer(children, root, null, work._onCommit); return work; };
8.updateContsainer里面使用了 currentTime 和 expirationTime,
currentTime是用來(lái)計(jì)算expirationTime,
expirationTime代表著優(yōu)先級(jí), 留在后續(xù)分析,
這里我們知道是同步更新 即 expirationTime = 1. 緊接著調(diào)用了updateContainerAtExpirationTime
function updateContainer(element, container, parentComponent, callback) { var current$$1 = container.current; var currentTime = requestCurrentTime(); var expirationTime = computeExpirationForFiber(currentTime, current$$1); return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback); }
9.updateContainerAtExpirationTime將current(即Fiber實(shí)例)提取出來(lái), 并作為參數(shù)傳入調(diào)用scheduleRootUpdate
function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) { // TODO: If this is a nested container, this won"t be the root. var current$$1 = container.current; ... return scheduleRootUpdate(current$$1, element, expirationTime, callback); }
到了這里告一段落, scheduleRootUpdate接下來(lái)就是React新版本異步渲染的核心了, 留在下一篇繼續(xù)解讀
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108919.html
摘要:為什么網(wǎng)頁(yè)性能會(huì)變高要回答這個(gè)問(wèn)題,需要回頭看是單線(xiàn)程的知識(shí)點(diǎn)。在分析的過(guò)程中,發(fā)現(xiàn)了的源碼中使用了很多鏈?zhǔn)浇Y(jié)構(gòu),回調(diào)鏈,任務(wù)鏈等,這個(gè)主要是為了增刪時(shí)性能比較高 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(異步狀態(tài)) React Fiber源碼分析 第四篇(歸納總結(jié)) 前言 Rea...
摘要:系列文章源碼分析第一篇源碼分析第二篇同步模式源碼分析第三篇異步狀態(tài)源碼分析第四篇?dú)w納總結(jié)前言是在版本中的大更新,利用了閑余時(shí)間看了一些源碼,做個(gè)小記錄流程圖源碼分析調(diào)用時(shí),會(huì)調(diào)用的方法,同時(shí)將新的作為參數(shù)傳進(jìn)會(huì)先調(diào)用獲取一個(gè)維護(hù)兩個(gè)時(shí)間一個(gè) 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(...
摘要:因?yàn)榘姹緦⒄嬲龔U棄這三生命周期到目前為止,的渲染機(jī)制遵循同步渲染首次渲染,更新時(shí)更新時(shí)卸載時(shí)期間每個(gè)周期函數(shù)各司其職,輸入輸出都是可預(yù)測(cè),一路下來(lái)很順暢。通過(guò)進(jìn)一步觀察可以發(fā)現(xiàn),預(yù)廢棄的三個(gè)生命周期函數(shù)都發(fā)生在虛擬的構(gòu)建期間,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段時(shí)間準(zhǔn)備前端招聘事項(xiàng)...
摘要:函數(shù)主要執(zhí)行兩個(gè)操作,一個(gè)是判斷當(dāng)前是否還有任務(wù),如果沒(méi)有,則從鏈中移除。 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(異步狀態(tài)) React Fiber源碼分析 第四篇(歸納總結(jié)) 前言 React Fiber是React在V16版本中的大更新,利用了閑余時(shí)間看了一些源碼,做個(gè)小記...
摘要:對(duì)于同一層級(jí)的一組子節(jié)點(diǎn),它們可以通過(guò)唯一進(jìn)行區(qū)分?;谝陨先齻€(gè)前提策略,分別對(duì)以及進(jìn)行算法優(yōu)化。鏈表的每一個(gè)節(jié)點(diǎn)是,而不是在之前的虛擬節(jié)點(diǎn)。是當(dāng)前層的第一個(gè)節(jié)點(diǎn)。再次提醒,是的一層。 文章首發(fā)于個(gè)人博客 這是我 Deep In React 系列的第二篇文章,如果還沒(méi)有讀過(guò)的強(qiáng)烈建議你先讀第一篇:詳談 React Fiber 架構(gòu)(1)。 前言 我相信在看這篇文章的讀者一般都已經(jīng)了解...
閱讀 2319·2021-11-10 11:35
閱讀 951·2021-09-26 09:55
閱讀 2436·2021-09-22 15:22
閱讀 2345·2021-09-22 15:17
閱讀 3754·2021-09-09 09:33
閱讀 1849·2019-08-30 11:22
閱讀 997·2019-08-30 10:57
閱讀 674·2019-08-29 16:10