摘要
經(jīng)過(guò)上一章,我們得到的FilberNode已經(jīng)具有了child和return屬性。一顆Filber樹的結(jié)構(gòu)已經(jīng)展現(xiàn)出來(lái)了。
那我們最終是想在頁(yè)面渲染真實(shí)的DOM。所以我們現(xiàn)在要在completeWork里,構(gòu)建出一顆離屏的DOM樹。
之前在說(shuō)FilberNode的屬性時(shí),我們提到過(guò)一個(gè)屬性stateNode。它就是用來(lái)保存每個(gè)FilberNode的真實(shí)DOM。
OK,現(xiàn)在我們開(kāi)干,準(zhǔn)備實(shí)現(xiàn)completeWork。
1.completeWork方法
在completeWork方法里,我們將剛才準(zhǔn)備好的FilberNode(最外層的)傳進(jìn)來(lái)。
completeWork方法也一定是一個(gè)遞歸的過(guò)程,每次調(diào)用的時(shí)候我們要判斷當(dāng)前的FilberNode的tag類型。
在判斷當(dāng)前的FilberNode是否具有stateNode,如果有,就說(shuō)明不是第一次更新。如果沒(méi)有,就說(shuō)明此時(shí)是mount第一次渲染的階段。
export const completeWork = (filberNode) => {
console.log(filberNode);
const tag = filberNode.tag
switch (tag) {
case HostComponent: {
if(filberNode.stateNode !== null){
//更新
}else{
completeHostComponent(filberNode)
}
break;
}
case HostText: {
break;
}
case HostRoot: {
}
}
}
2.創(chuàng)建真實(shí)DOM
拿到每個(gè)FilberNode后,如果他是HostComponent類型的。我們實(shí)現(xiàn)出completeWork方法。
首先我們可以通過(guò)拿到FilberNode的type(div,span),知道真實(shí)DOM的類型,通過(guò)document的方法創(chuàng)建出對(duì)應(yīng)的element。
然后再通過(guò)return屬性,拿到當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。并且在父節(jié)點(diǎn)的stateNode中,添加創(chuàng)建好的element。
function completeHostComponent(filberNode) {
const type = filberNode.type;
const element = document.createElement(type);
filberNode.stateNode = element;
const parent = filberNode.return;
if(parent && parent.stateNode && parent.tag === HostComponent) {
parent.stateNode.appendChild(element)
}
completeWork(filberNode.child)
}
對(duì)于HostText類型,我們可以直接創(chuàng)建文本節(jié)點(diǎn),然后掛載在stateNode上面即可:
function completeHostText(filberNode) {
const content = filberNode.pendingProps;
const element = document.createTextNode(content)
filberNode.stateNode = element
const parent = filberNode.return;
if(parent && parent.stateNode && parent.tag === HostComponent) {
parent.stateNode.appendChild(element)
}
}
這里值得注意的是,在創(chuàng)建真實(shí)DOM的時(shí)候,這里并沒(méi)有處理props相關(guān)的內(nèi)容。只創(chuàng)建了對(duì)應(yīng)的DOM結(jié)構(gòu)。
3.掛載finishedWork
最后我們將執(zhí)行完beginWork和completeWork的FilberRootNode。掛載在hostRootFilber上面,
function updateContainer(root, element) {
const hostRootFilber = root.current;
const update = createUpdate(element);
hostRootFilber.updateQueue = createUpdateQueue()
enqueueUpdate(hostRootFilber.updateQueue, update);
beginWork(hostRootFilber);
completeWork(hostRootFilber);
root.finishedWork = hostRootFilber;
}
4.問(wèn)題
這里我們打印一下root,可以看到:
root的current和finishedWork其實(shí)是一模一樣的,但React其實(shí)并非是這樣處理的。經(jīng)過(guò)beginWork和completeWork處理的節(jié)點(diǎn),并不是最外層的FilberNode,而是它的alternate。
所以我們調(diào)用beginWork和completeWork處理的應(yīng)該是FilberNode的alternate。
5.效果
為了看到效果我們可以寫一個(gè)方法,當(dāng)然這個(gè)方法里面內(nèi)容不可能這沒(méi)少。但是我們可以先實(shí)現(xiàn)一下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-638807.html
export function commitWork(filberRootNode) {
const container = filberRootNode.container;
const child = filberRootNode.finishedWork.child.stateNode;
container.appendChild(child)
}
然后再beginWork和completeWork執(zhí)行完后,執(zhí)行這個(gè)方法。
就可以看到頁(yè)面正產(chǎn)渲染節(jié)點(diǎn)了。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-638807.html
到了這里,關(guān)于React源碼解析18(4)------ completeWork的工作流程【mount】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!