從頭實現乙個簡易版React(一)

2021-09-14 02:39:58 字數 2676 閱讀 7242

工作中使用react也很長一段時間了,雖然對它的用法,原理有了一定的了解,但是總感覺停留在表面。本著知其然知其所以然的態度,我試著去看了react原始碼,幾天下來,發現並不能看懂,反而更加雲裡霧裡了- -!。既然看不懂,那就看看社群前輩們寫的一些原始碼分析文章以及實現思路吧,又這麼過了幾天,總算是摸清點思路,於是在參考了前輩們的基礎上,實現了乙個簡易版的react。

這個系列我打算分為3節,第一節介紹下實現的思路以及結構,第二節講渲染,第三節講更新。

react的一切都基於virtual dom,我們第一步自然先實現它,如下:

/**

* @param type :代表當前的節點屬性

* @param key :用來標識element,用於優化以後的更新

* @param props:節點的屬性

*/function vdom(type, key, props)

實現了vdom後,理所需要乙個方法來將我們寫的元素轉化為vdom。一般我們都是jsx來建立元素的,但它只不過是react.createelment的語法糖。所以,接下來,我們要實現的就是createelement方法:

function createelement(type, config, ...children) 

config = config || {}

// 獲取key,用來標識element,方便以後高效的更新

const = config

let propname = ''

// 複製config裡的內容到props

for (propname in config)

} // 轉化children

if (children.length === 1 && array.isarray(children[0])) else

return new vdom(type, key, props)

}

這段**也非常簡單,根據我們傳入的引數,生成對應的vdom

我們所建立的vdom型別分為3種:

不同的型別,肯定有不同的渲染和更新邏輯,我們把這些邏輯與vdom一起,封裝成對應的reactcomponent類,通過reactcomponent類控制vdom,這裡我把它們命名為reacttextcomponent,reactdomcomponent,reactcompositecomponent,分別對應三種型別。

首先是基類reactcomponet:

// component基類,用來處理不同的虛擬dom更新,渲染

class component

}

接著再讓不同型別的component繼承這個基類,每種component型別都有mount和update兩個方法,用來執行渲染和更新

class reactdomcomponent extends reactcomponent 

// 更新

updatecomponent() {}

}

class reactcompositecomponent extends reactcomponent 

// 更新

updatecomponent() {}

}

class reacttextcomponent extends reactcomponent 

// 更新

updatecomponent() {}

}

實現了reactcomponent後,我們自然需要乙個入口去得到reactcomponent並呼叫它的mount。在使用react時,通常都是通過

import react from 'react'

import reactdom from 'react-dom'

}

這段**來充當渲染的入口,下面我們來實現這個入口,(為了方便說明,我把render方法也放在了react物件中)

import component from './component'

import createelement from './reactelement'

import instantiatereactcomponent from './component/util'

import $ from 'jquery'

const react =

}

由於渲染和更新都已經封裝在不同的reactcomponent裡,所以,這裡也需要乙個方法,根據不同的vdom型別生成對應的reactcomponent,下面我們就來實現這個方法:

// component工廠,用來返回乙個component例項

function instantiatereactcomponent(node)

// 瀏覽器預設節點的情況

if (typeof node === 'object' && typeof node.type === 'string')

// 自定義的元素節點

if (typeof node === 'object' && typeof node.type === 'function')

}

然後再呼叫入口reactcomponent的mount方法,獲取渲染內容,再將其渲染出來就行。

參考資料,感謝幾位前輩的分享:

陳屹 《深入react技術棧》

實現乙個簡易版的Tomcat 十二

如何解析xml檔案?這裡會用到dom4j解析,如下 通過解析config目錄下的web.xml檔案 並將其中的中間的文字作為key 將中間的文字作為value try catch exception e 根據給定的資源字尾名獲取對應的content type的值 param ext return p...

基於vue搭建乙個簡易版豆瓣

前段日子業餘時看了下vue,想著怎麼也得寫個例項來加深一下,於是便基於vue構建了乙個簡易版豆瓣。由於工作中使用的並不是vue框架,對vue的了解也不夠深入,這也是本人第一次寫技術博文,因此,有紕漏之處還請大家批評指正。專案簡介 本專案主要是基於vue,構建乙個簡易版豆瓣,實現將讀書 電影 同城活動...

寫乙個自己的簡易版vue

剛到家疫情就開始爆發,恰巧家裡沒有網,手機網路在老家的速度就像拖拉機,每天躲在家裡,還好剛到老家時搞了些口罩,不至於返程時沒有口罩可帶。手機的網路速度到底什麼樣呢,用vue cli建個專案就在那一直install,還有可能中途失敗,哎。沒法練習vue了就把自己寫好的簡易版vue拿出來又擼了擼,還有點...