不管你信不信,這次真的33行代碼實(shí)現(xiàn)個React
編者按:本文作者李松峰,資深技術(shù)圖書譯者,翻譯出版過40余部技術(shù)及交互設(shè)計專著,現(xiàn)任360奇舞團(tuán)Web前端開發(fā)資深專家,360前端技術(shù)委員會委員、W3C AC代表。
一位倫敦的Python工程師Oliver Russell最近做了一個好玩的嘗試,用33行代碼“實(shí)現(xiàn)了”React。
他實(shí)現(xiàn)的“React”主要涉及如下抽象:
我們傳一個取得狀態(tài)并返回虛擬DOM的函數(shù)
“React”在瀏覽器中將虛擬DOM渲染為真實(shí)DOM
狀態(tài)改變,“React”再次運(yùn)行函數(shù)并返回新虛擬DOM
“React”高效更新真實(shí)DOM,以匹配新虛擬DOM
由此可見,這個實(shí)現(xiàn)的功能還十分有限。只涉及虛擬DOM生成、差異比較和真實(shí)DOM渲染。
全部實(shí)現(xiàn)代碼如下圖所示。
無注釋版:https://github.com/leontrolski/leontrolski.github.io/blob/master/33-line-react.js
有注釋版:https://github.com/leontrolski/leontrolski.github.io/blob/master/33-line-react-with-comments.js
這個實(shí)現(xiàn)參考了Mithril(https://mithril.js.org/)的語法。對外主要暴露了兩個函數(shù):
m():Mithril風(fēng)格的hyperscript輔助函數(shù),用于創(chuàng)建虛擬DOM
m.render():DOM掛載與渲染邏輯
其中m()接收如下參數(shù):
標(biāo)簽名(如 'tr')及 .分隔的類名
(可選的){string: any}對象,包含添加給DOM節(jié)點(diǎn)的所有屬性
任意嵌套的子節(jié)點(diǎn),可以是其他虛擬DOM或字符串
返回虛擬DOM對象,比如:
{
????tag:?'div',
????attrs:?{},
????classes:?[],
????children:?[
????????{
????????????tag:?'h3',
????????????attrs:?{},
????????????classes:?[],
????????????children:?[
????????????????'current player:?x'
????????????]
????????},
????????{
????????????tag:?'table',
????????????attrs:?{},
????????????classes:?[],
????????????children:?[
????????????????{
????????????????????tag:?'tr',
????????????????????attrs:?{},
????????????????????classes:?[],
????????????????????children:?[
...
雖然在很多人眼里這還是一個“玩具”,但用Oliver Russell的話說:“(對于一般的單面應(yīng)用)用這33行代碼替換React也不會有人看得出來?!睘榇?,他還基于這個“React”寫了幾個例子。
Noughts and Crosses
https://leontrolski.github.io/33-line-react.html
Calendar Picker
https://leontrolski.github.io/33-line-react-calendar.html
Snake
https://leontrolski.github.io/33-line-react-snake.html
筆者也基于這個“React”寫了一個非常簡單的ToDo:
class?toDoDemo?{
??constructor()?{
????this.todos?=?[]
????this.render?=?()?=>?m.render(
??????document.getElementById('example'),
??????{children:?[this.showToDos()]},
????)
????this.render()
??}
??showToDos()?{
????return?m('div',?[
??????m('h3',?'ToDo示例'),
??????m('input',?{?placeholder:?'添加todo'?}),
??????m('button',
????????{
??????????onclick:?(e)?=>?this.addTodo(e)
????????},
????????'+'
???????),
??????m('ul',
????????this.todos.map((item,?i)?=>?m('li',?[
??????????m('span',?item),
??????????m('button',
????????????{
??????????????onclick:?()?=>?this.removeTodo(i)
????????????},
????????????'-'
???????????)
????????])))
??????])
??}
??removeTodo(i)?{
????this.todos.splice(i,1)
????this.render()
??}
??addTodo(e)?{
????const?input?=?e.target.previousSibling
????const?todo?=?input.value
????if(!todo.trim())?return
????input.value?=?''
????this.todos.push(todo)
????this.render()
??}
}
new?toDoDemo()
https://code.h5jun.com/zelix/
有興趣的的讀者不妨花點(diǎn)時間研究一下這個“33-line-react”,包括上面的幾個示例。
參考鏈接:
https://leontrolski.github.io/33-line-react.html
https://news.ycombinator.com/item?id=22776753
如果你喜歡探討技術(shù),或者對本文有任何的意見或建議,非常歡迎加魚頭微信好友一起探討,當(dāng)然,魚頭也非常希望能跟你一起聊生活,聊愛好,談天說地。魚頭的微信號是:krisChans95 也可以掃碼關(guān)注公眾號,訂閱更多精彩內(nèi)容。




