掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
大家好,我是卡頌。

創(chuàng)新互聯(lián)建站主營(yíng)克拉瑪依網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,app軟件開(kāi)發(fā),克拉瑪依h5小程序開(kāi)發(fā)搭建,克拉瑪依網(wǎng)站營(yíng)銷推廣歡迎克拉瑪依等地區(qū)企業(yè)咨詢
周末沒(méi)啥事,準(zhǔn)備找個(gè)優(yōu)秀且代碼量不多的庫(kù)學(xué)習(xí)下。最終選擇了最近發(fā)布的petite-vue,原因如下:
[[410857]]
但是周末時(shí)間這么寶貴,而且我都4年沒(méi)用過(guò)Vue了,如何才能高效學(xué)習(xí)源碼呢?
最好是「在不看源碼的情況下把源碼學(xué)了」。
接下來(lái),我就以petite-vue為例為大家示范學(xué)源碼的正確姿勢(shì)。
可以將petite-vue理解為:用真實(shí)DOM取代Vue模版的簡(jiǎn)易Vue。
比如如下Demo:
{{count}}
div及其子孫節(jié)點(diǎn)是真實(shí)的DOM標(biāo)簽,所以頁(yè)面初始化時(shí)如下:
接著執(zhí)行如下代碼,完成petite-vue初始化:
- createApp({count: 0}).mount()
此時(shí)頁(yè)面:
讀框架源碼切忌一上手就從入口函數(shù)一路調(diào)試,很容易就懵逼了。正確的方式是像剝洋蔥一樣一層一層剝開(kāi):
[[410860]]
這好像是大蒜?
所以,讓我們先從Performance面板看看「首屏渲染」的調(diào)用棧:
調(diào)用棧大體分為藍(lán)框、紅框兩部分,先看左邊藍(lán)框部分:
通過(guò)createContext與reactive關(guān)鍵詞判斷大概是創(chuàng)建響應(yīng)式上下文。至于響應(yīng)式的含義,我們還不清楚。
接著看右邊紅框部分:
從調(diào)用棧深度、頁(yè)面渲染的效果我們猜測(cè),這部分做的工作包括:
接下來(lái),我們來(lái)驗(yàn)證猜想。
注意,到目前為止,我們一行源碼都還沒(méi)看
調(diào)用棧中walk與walkChildren被調(diào)用多次,大概率他們就是具體遍歷工作執(zhí)行的方法,讓我們確認(rèn)下。
在源碼walk方法中打上log:
- export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
- console.log('walk', node);
- // ...
- }
排除換行符"\n "對(duì)應(yīng)的文本節(jié)點(diǎn),打印順序如下:
- walk div
- walk
- walk "add 1"
- walk
0
- walk "0"
從打印結(jié)果看,這是個(gè)「深度優(yōu)先遍歷」(如果有子節(jié)點(diǎn)就遍歷子節(jié)點(diǎn),沒(méi)有子節(jié)點(diǎn)就遍歷兄弟節(jié)點(diǎn))
顯然,petite-vue mount時(shí)采用「深度優(yōu)先遍歷」,并對(duì)遍歷到的每個(gè)與「上下文狀態(tài)」相關(guān)的DOM節(jié)點(diǎn)進(jìn)行處理。
在Demo中,上下文包含狀態(tài){count: 0}:
- createApp({count: 0}).mount()
在遍歷后
{{count}}
變?yōu)?p>0。接下來(lái)我們需要確認(rèn)雙向綁定的作用范圍,即:
觸發(fā)更新后,多大范圍的DOM會(huì)被重新遍歷并執(zhí)行相應(yīng)DOM操作?
打開(kāi)Performance后,點(diǎn)擊觸發(fā)更新:
可以看到,沒(méi)有任何walk、walkChildren(或類似遍歷過(guò)程),只調(diào)用了reactiveEffect一個(gè)方法就更新了DOM。
這意味著mount時(shí)的深度優(yōu)先遍歷建立了狀態(tài)與更新DOM的方法之間一一對(duì)應(yīng)的關(guān)系。
因?yàn)閷?duì)應(yīng)關(guān)系確定了,就不再需要額外的遍歷過(guò)程確定需要變化的DOM。
當(dāng)更新?tīng)顟B(tài)后,只需要找到與他有關(guān)系的更新DOM的方法執(zhí)行就行。
比如:將count狀態(tài)與如下函數(shù)建立聯(lián)系:
- function setCount(value) {
- p.textContent = value;
- }
每當(dāng)count變化后調(diào)用setCount(count)就能更新p對(duì)應(yīng)DOM。
所以,petite-vue的工作原理,主要包括兩點(diǎn):
{{count}}
)建立狀態(tài)與更新DOM的方法之間一一對(duì)應(yīng)的關(guān)系可以看到,即使不深入源碼,也能大體了解工作流程。
如果你想更進(jìn)一步,比如了解「關(guān)系是如何建立的」(涉及到「響應(yīng)式更新」),那么就需要深入源碼了。
這里推薦Vue Mastery的Vue 3 Reactivity課程,可以補(bǔ)齊「響應(yīng)式更新」這塊知識(shí)。
本文介紹了復(fù)雜框架源碼的閱讀辦法 —— 即從抽象到具體。
當(dāng)掌握整體工作流程與響應(yīng)式更新后,再閱讀自己感興趣的部分才不至于陷入龐大的代碼量中。
你,學(xué)廢了么?

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流