React中updateContainerImpl方法更新容器源碼解析
概覽
在ReactDOMRoot的render和unmount方法中均調(diào)用了updateContainerImpl方法,該方法是React中更新容器的核心方法,負(fù)責(zé)創(chuàng)建和調(diào)度更新。
源碼分析
updateContainerImpl
updateContainerImpl方法源碼實(shí)現(xiàn)如下:
function updateContainerImpl(
rootFiber, //根Fiber節(jié)點(diǎn)
lane, // 更新優(yōu)先級(jí)
element, //要渲染的React元素
container, // Fiber根節(jié)點(diǎn)容器
parentComponent, // 父組件
callback // 更新完成后的回調(diào)函數(shù)
) {
// 獲取子樹(shù)的上下文,會(huì)返回一個(gè)空對(duì)象
parentComponent = getContextForSubtree(parentComponent);
// 若Fiber根節(jié)點(diǎn)容器上下文為空,則設(shè)置其為獲取到的上下文(空對(duì)象);否則設(shè)置待處理的上下文為空對(duì)象
null === container.context
? (container.context = parentComponent)
: (container.pendingContext = parentComponent);
// 根據(jù)優(yōu)先級(jí)車(chē)道創(chuàng)鍵更新對(duì)象
container = createUpdate(lane);
// 將要渲染的React元素作為更新對(duì)像的載荷
container.payload = { element: element };
// 若回調(diào)未定義,則設(shè)為null,否則保留原值
callback = void 0 === callback ? null : callback;
// 若回調(diào)不為null,則將其設(shè)為更新對(duì)象的callback屬性值
null !== callback && (container.callback = callback);
// 將更新對(duì)象添加到Fiber節(jié)點(diǎn)的更新隊(duì)列,并獲取FiberRoot
element = enqueueUpdate(rootFiber, container, lane);
// 判斷 若返回的更新對(duì)象不為null,則調(diào)度更新
null !== element &&
(scheduleUpdateOnFiber(element, rootFiber, lane),
entangleTransitions(element, rootFiber, lane));
}
createUpdate
createUpdate接受一個(gè)參數(shù)車(chē)道優(yōu)先級(jí)(lane),返回一個(gè)更新對(duì)象,其對(duì)象類(lèi)型為Update,Update會(huì)被放入更新隊(duì)列中等待調(diào)度執(zhí)行,其優(yōu)先級(jí)為參數(shù)lane,tag為UpdateState:0,其實(shí)現(xiàn)如下:
function createUpdate(lane){
return {
lane: lane, // 更新優(yōu)先級(jí)
tag: UpdateState, // 其值為1 ,表示更新類(lèi)型
payload: null, // 更新載荷
callback: null, // 回調(diào)函數(shù)
next: null // 指向下一個(gè)更新
}
}
enqueueUpdate
enqueueUpdate方法用于將更新對(duì)象加入Fiber節(jié)點(diǎn)的更新隊(duì)列,其源碼實(shí)現(xiàn)如下:
function enqueueUpdate(fiber, update, lane) {
// 獲取Fiber節(jié)點(diǎn)上的更新隊(duì)列updateQueue
var updateQueue = fiber.updateQueue;
// 若更新隊(duì)列為空,則返回null,此時(shí)Fiber節(jié)點(diǎn)已被卸載
if (null === updateQueue) return null;
// 獲取共享隊(duì)列
updateQueue = updateQueue.shared;
// 檢查是否是渲染更新階段
if (0 !== (executionContext & 2)) {
// 獲取共享隊(duì)列的最后一個(gè)節(jié)點(diǎn)
var pending = updateQueue.pending;
// 判斷最后一個(gè)節(jié)點(diǎn)是否為空
null === pending
? (update.next = update) // 將更新對(duì)象update的next指向自身
: ((update.next = pending.next), (pending.next = update)); //否則將更新對(duì)象的next指向最后一個(gè)節(jié)點(diǎn)的next,并且將最后一個(gè)節(jié)點(diǎn)的next指向更新對(duì)象,即將更新對(duì)象插入到環(huán)形鏈表的末尾
// 更新pending指針
updateQueue.pending = update;
// 從Fiber節(jié)點(diǎn)中獲取FiberRoot
update = getRootForUpdatedFiber(fiber);
// 標(biāo)記fiber節(jié)點(diǎn)中的優(yōu)先級(jí)
markUpdateLaneFromFiberToRoot(fiber, null, lane);
// 最后返回FiberRoot
return update;
}
// 若不是渲染更新階段,則依次執(zhí)行enqueueUpdate$1,getRootForUpdatedFiber,最后返回getRootForUpdatedFiber的結(jié)果FiberRoot
// 調(diào)用enqueueUpdate$1方法就是將相關(guān)參數(shù)放到并發(fā)隊(duì)列concurrentQueues中
enqueueUpdate$1(fiber, updateQueue, update, lane);
return getRootForUpdatedFiber(fiber);
}
getRootForUpdatedFiber
Fiber節(jié)點(diǎn)的return始終是指向父節(jié)點(diǎn),因此通過(guò)不斷追溯return可以找到根節(jié)點(diǎn);
function getRootForUpdatedFiber(sourceFiber) {
// 判斷某計(jì)數(shù)器,暫且不提
if (50 < nestedUpdateCount)
throw (
((nestedUpdateCount = 0),
(rootWithNestedUpdates = null),
Error(formatProdErrorMessage(185)))
);
for (var parent = sourceFiber.return; null !== parent; )
(sourceFiber = parent), (parent = sourceFiber.return);
// 判斷當(dāng)前Fiber節(jié)點(diǎn)的根節(jié)點(diǎn)類(lèi)型是否為HostRoot,若是,則返回其DOM元素,否則返回null
return 3 === sourceFiber.tag ? sourceFiber.stateNode : null;
}
scheduleUpdateOnFiber
調(diào)用enqueueUpdate方法更新相關(guān)隊(duì)列后,會(huì)拿到FiberRoot,若FiberRoot不為null,則調(diào)用scheduleUpdateOnFiber進(jìn)行調(diào)度更新。
entangleTransitions
entangleTranslations方法用于糾纏過(guò)渡更新,主要有3個(gè)作用:
- 將當(dāng)前更新與正在進(jìn)行的過(guò)渡更新糾纏
- 確保過(guò)渡更新的正確順序
- 處理并發(fā)模式下的更新沖突
到此這篇關(guān)于React中updateContainerImpl方法更新容器源碼解析的文章就介紹到這了,更多相關(guān)React updateContainerImpl更新容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React19 Diff 算法的具體實(shí)現(xiàn)
本文主要介紹了React19 Diff 算法的具體實(shí)現(xiàn),該算法用于高效地更新虛擬DOM,它通過(guò)優(yōu)化傳統(tǒng)樹(shù)diff算法,將復(fù)雜度從O(n^3)降低到O(n),感興趣的可以了解一下2026-05-05
ReactNative實(shí)現(xiàn)的橫向滑動(dòng)條效果
本文介紹了ReactNative實(shí)現(xiàn)的橫向滑動(dòng)條效果,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),補(bǔ)充介紹了ReactNative基于寬度變化實(shí)現(xiàn)的動(dòng)畫(huà)效果,感興趣的朋友跟隨小編一起看看吧2024-02-02
react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式
這篇文章主要介紹了react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
react render props模式實(shí)現(xiàn)組件復(fù)用示例
本文主要介紹了react render props模式實(shí)現(xiàn)組件復(fù)用示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
react裝飾器與高階組件及簡(jiǎn)單樣式修改的操作詳解
這篇文章主要介紹了react裝飾器與高階組件及簡(jiǎn)單樣式修改的操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09

