React從零實現 元件渲染和setState

2021-09-11 15:36:11 字數 2905 閱讀 5611

在react中元件大體分為兩種,一種是乙個純函式,沒有生命週期的。另乙個通過繼承自react.component的類來實現。

我們先來寫乙個component類。

class

component

; }

setstate(partialstate) , this.state, partialstate);

updatecomponent(this);

}}複製**

我們完成了乙個component類,同時該類的例項有乙個setstate函式,用來更新該元件。updatecomponent我們下面會實現它。

我們前面提到過虛擬節點的概念,但是我們但是直接使用element下面這種形式來作為我們的虛擬節點的。

}複製**

但是但我們要更新我們的元件是,我們需要記錄element和dom節點之間的關係,為了不汙染element,我們引入我們新的虛擬節點的概念,我這裡稱之為node(實際情況並不是如此,這裡只是為了方便命名)。之後相關的虛擬幾點命名也會採用***node的命名方式。下面我們來改造我們以前的render函式,將其重新命名為createnode並且只接受乙個型別為element的引數,其返回值為乙個node型別的節點。

function

createnode(element) = element;

// 是文字節點則建立文字節點,這裡建立乙個空的文字節點,後面利用nodevalue直接給該節點賦值

const istextnode = type === 'text element';

const iscomponent = typeof type === 'function';

// 元件情況

if (iscomponent) else

// 建立node節點

const childnode = createnode(childelement);

const dom = childnode.dom;

const node = ;

// 在例項中記錄舊的node節點,以便之後進行更新

instance._internalnode = node;

return node;

}// dom情況

const childelements = props.children || ;

const childdom = istextnode

? document.createtextnode('')

: document.createelement(type);

const isevent = name => name.startswith('on');

const isattribute = name => !isevent(name) && name !== 'children';

// 繫結事件

object.keys(props).filter(isevent).foreach(name => );

// 新增屬性

object.keys(props).filter(isattribute).foreach(name => );

// 遞迴建立

const childnodes = childelements.map(createnode);

// 掛載到父節點

return

}複製**

從上面可以看到,我們的虛擬節點node記錄我們需要的資訊,如element、dom、childrennodes等,它是乙個物件,結構是:

複製**

有了createnode函式,現在再寫我們的render函式:

function

render(element, containerdom)

複製**

render函式中,我們所需要做的就是獲取虛擬節點並直接渲染它,並且需要同時渲染其孩子節點,最後掛載到根元素就完成了我們的渲染過程。

到這裡我們已經可以渲染元件了,我們還有乙個setstate需要實現,實現setstate就需要我們上面提到的updatecomponent函式了。

updatecomponent接收乙個元件例項,它需要做哪些事情那?我們想一下,其實很簡單,它只需要拿到舊的dom節點,然後渲染新的dom節點,最後將舊的替換為新的就能夠實現重新整理的效果了。在這裡我們上面在例項中儲存的_internalnode就能發揮作用了。它記錄了舊節點的所有資訊。下面來實現吧:

function

updatecomponent(instance)

複製**

實現完成,現在我們已經可以更新我們的元件了。這是codepen中的例項。

在元件的實現過程中為了簡化,我們去掉了元件的生命週期,它需要作為乙個個鉤子掛載在不同的位置。如果你使用了例項,或者自己跑過之後會發現,我們每次更新都要重新渲染整個dom樹,這樣代價很大,在react中使用了一種diff演算法來重用不需要更新的節點和屬性,下一節我們就來實現react中的diff演算法reconciliation

實現react系列列表:

React中利用 key 實現元件重新渲染

最近在專案實踐中,發現react中可以利用key實現子元件的重新渲染,具體場景 需要切換下拉列表時,對應的榜單也要替換成該輪的資料 如下 render this state round表示選中的選單的索引 return record wrap selectedindex showmenu oncha...

React建立元件和渲染元件的幾種方法

渲染元件 工廠 無狀態 函式 最簡潔,推薦使用 function mycomponent1 自己定義的元件類必須要繼承react的核心元件 class mycomponent3 extends react.component var mycomponent2 react.createclass re...

實現乙個react系列二 渲染元件

在上一節jsx和虛擬dom中,我們了解了react中的jsx到虛擬dom,以及如何將虛擬dom渲染成真實的dom。在這一節中,我們將會了解react中元件是如何渲染的。在react中,元件有兩種使用方法 import react from react 類定義的元件 class hello exten...