摘要
經(jīng)過(guò)之前的幾篇文章,我們實(shí)現(xiàn)了基本的jsx,在頁(yè)面渲染的過(guò)程。但是如果是通過(guò)函數(shù)組件寫(xiě)出來(lái)的組件,還是不能渲染到頁(yè)面上的。
所以這一篇,主要是對(duì)之前寫(xiě)得方法進(jìn)行修改,從而能夠顯示函數(shù)組件,所以現(xiàn)在我們?cè)趇ndex.js文件中,修改一下jsx的寫(xiě)法。修改成函數(shù)組件:
import jsx from '../src/react/jsx.js'
import ReactDOM from '../src/react-dom/index'
const root = document.querySelector('#root');
function App() {
return jsx("div", {
ref: "123",
children: jsx("span", {
children: "456"
})
});
}
ReactDOM.createRoot(root).render(<App />)
這里因?yàn)樾枰褂梦覀冏约旱膉sx方法。所以在App里面返回的依舊是通過(guò)之前的方式進(jìn)行調(diào)用。
1.修改reconcileChildren方法
我們來(lái)回憶一下,在beginWork階段,我們主要是通過(guò)ReactElement,創(chuàng)建FilberNode。而reconcileChildren,就是創(chuàng)建FilberNode的方法。
在之前我們只處理了HostText類(lèi)型和HostComponent類(lèi)型,所以在這個(gè)方法里面,我們要對(duì)函數(shù)類(lèi)型進(jìn)行兼容,而作為函數(shù)組件的ReactElment,它最顯而易見(jiàn)的特點(diǎn)就是type的值是一個(gè)函數(shù)。
例如上面的App組件,對(duì)應(yīng)的ReactElement的type就是App。所以我們可以通過(guò)type來(lái)判斷組件的類(lèi)型:
function reconcileChildren(element) {
let tag;
if(typeof element.type === 'function') {
tag = FunctionComponent
}
//其他代碼
console.log(filberNode)
return filberNode
}
我們打印一下看看,這個(gè)函數(shù)組件是否滿(mǎn)足預(yù)期:
2.updateFunctionComponent方法
現(xiàn)在有了tag為FunctionComponent類(lèi)型的FilberNode,在beginWork里面,我們就要對(duì)這個(gè)類(lèi)型的FilberNode進(jìn)行處理:
function beginWork(nowFilberNode) {
switch (nowFilberNode.tag) {
//其他代碼
case FunctionComponent: {
return updateFunctionComponent(nowFilberNode)
}
//其他代碼
}
}
現(xiàn)在我們來(lái)實(shí)現(xiàn)updateFunctionComponent方法。
之前對(duì)于HostComponent類(lèi)型的FilberNode,它的子節(jié)點(diǎn)其實(shí)就是它對(duì)應(yīng)的ReactElement。
但是對(duì)于函數(shù)類(lèi)型的FilberNode,我們想一下不就是它自己的返回值嘛?所以我們直接調(diào)用這個(gè)函數(shù)就能拿到它的子FilberNode了。
function updateFunctionComponent(filberNode) {
const nextChildren = filberNode.type();
const newFilberNode = reconcileChildren(nextChildren);
filberNode.child = newFilberNode;
newFilberNode.return = filberNode;
beginWork(newFilberNode)
}
2.修改completeWork方法
對(duì)于completeWork方法, 它的主要作用(目前)是給對(duì)應(yīng)的FilberNode增加stateNode,而函數(shù)組件并沒(méi)有自己對(duì)應(yīng)的StateNode,所以直接繼續(xù)遞歸就可以了:
export const completeWork = (filberNode) => {
const tag = filberNode.tag
switch (tag) {
//其他代碼。。。
case FunctionComponent: {
completeWork(filberNode.child)
}
}
}
3.修改commitWork方法
對(duì)于之前的commitWork,我們是直接將最外層的FilberNode的stateNode掛載了容器上,現(xiàn)在由于最外層的可能是FunctionComponent,它是沒(méi)有自己的stateNode的。所以我們要找到具有stateNode的最外層FilberNode。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-646542.html
import { HostComponent } from "./filberNode";
export function commitWork(filberRootNode) {
const container = filberRootNode.container;
let node = filberRootNode.finishedWork;
while( node.tag !== HostComponent ){
node = node.child
}
container.appendChild(node.stateNode)
}
OK,經(jīng)過(guò)上面的修改,我們的App組件也可以正常渲染了。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-646542.html
到了這里,關(guān)于React源碼解析18(5)------ 實(shí)現(xiàn)函數(shù)組件【修改beginWork和completeWork】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!