![]()
2023年Stack Overflow調(diào)研顯示,React連續(xù)6年霸榜最常用Web框架,但87%的開發(fā)者承認(rèn)從未看過其源碼。不是不想,是不知道從哪下手。
Virtual DOM(虛擬文檔對象模型)這個詞你聽了無數(shù)遍。它到底是什么?一個性能優(yōu)化?一個數(shù)據(jù)結(jié)構(gòu)?還是React用來忽悠投資人的概念?
Rich Harris,Svelte框架的作者,2018年扔下一句話:「Virtual DOM不是性能優(yōu)化,它是在DOM操作之上加了一層額外工作。」這句話至今沒人反駁。真正的價值在于編程模型——你描述UI應(yīng)該長什么樣,框架算出最小變更集。不是「怎么做到」,是「做成什么樣」。
本文用100行原生JavaScript,零構(gòu)建工具、零npm依賴、零JSX,手搓一個完整Virtual DOM引擎。四個函數(shù):h、render、diff、patch。裝完樹、比完差異、打完補(bǔ)丁,React的魔法就變成你能講清的工程權(quán)衡。
第一步:把HTML變成JavaScript對象
你平時寫`
Count: 0
Virtual DOM的核心想法:用純JavaScript對象描述同樣的結(jié)構(gòu)。
![]()
最終API長這樣:
const vdom1 = h('div', { id: 'app' },
h('p', {}, 'Count: 0')
);
const container = render(vdom1);
document.body.appendChild(container);
// 數(shù)字變了
const vdom2 = h('div', { id: 'app' },
h('p', {}, 'Count: 1')
);
const patches = diff(vdom1, vdom2);
patch(container, patches);
// 結(jié)果:只有文本節(jié)點(diǎn)更新,div和p原封不動
四個函數(shù),沒有類、沒有事件總線、沒有響應(yīng)式系統(tǒng)。h負(fù)責(zé)創(chuàng)建,render負(fù)責(zé)掛載,diff負(fù)責(zé)比較,patch負(fù)責(zé)應(yīng)用。
vnode:內(nèi)存里的DOM說明書
h()返回的東西叫vnode(虛擬節(jié)點(diǎn)),就是一個普通JavaScript對象:
const vnode = {
type: 'p',
props: {},
children: [{ type: 'TEXT_NODE', props: { nodeValue: 'Count: 0' } }]}; br/>};
vnode樹完全鏡像DOM結(jié)構(gòu),但只活在內(nèi)存里,全是純JS對象。沒有特殊原型,沒有框架魔法。它只是一份DOM節(jié)點(diǎn)的說明書——僅此而已。
![]()
真實(shí)DOM對它一無所知,直到render()遍歷這棵樹,造出真正的元素。
為什么值得親手寫一遍
React用了10年教會開發(fā)者「聲明式UI」這個詞,卻沒幾個人能解釋reconciliation(協(xié)調(diào)算法)到底在協(xié)調(diào)什么。你遇到無法解釋的bug、看不懂的性能分析、或者腦子里缺了塊拼圖的時候,這層抽象就成了黑箱。
100行代碼之后,黑箱變透明。你會明白為什么key屬性不能亂用,為什么setState可能是異步的,為什么有些組件該拆、有些不該拆。
這不是考古,是還賬。用了這么久,總得知道機(jī)器在替你做什么。
打開編輯器,再開一個瀏覽器標(biāo)簽。這就夠了。
你寫完之后,會刪掉它繼續(xù)用React,還是發(fā)現(xiàn)自己其實(shí)不需要那么多抽象?
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.