前言
怎麼快怎麼來,你們的時間都寶貴,用最短的時間學到最多的知識。
咱們能夠將petite-vue
理解爲:用真實DOM
取代Vue
模版的簡易Vue
。html
好比以下Demo
:vue
<script type="module"> import { createApp } from '../src' createApp({count: 0}).mount() </script> <div v-scope> <button @click="count++">add 1</button> <p>{{count}}</p> </div> 複製代碼
div
及其子孫節點是真實的DOM
標籤,因此頁面初始化時以下:node
接着執行以下代碼,完成petite-vue
初始化:react
createApp({count: 0}).mount() 複製代碼
此時頁面:git
讀框架源碼切忌一上手就從入口函數一路調試,很容易就懵逼了。正確的方式是像剝洋蔥同樣一層一層剝開:github
因此,讓咱們先從Performance
面板看看首屏渲染的調用棧:框架
調用棧大致分爲藍框、紅框兩部分,先看左邊藍框部分:函數
經過createContext
與reactive
關鍵詞判斷大概是建立響應式上下文
。至於響應式
的含義,咱們還不清楚。post
接着看右邊紅框部分:url
從調用棧深度、頁面渲染的效果咱們猜想,這部分作的工做包括:
-
遍歷
DOM
-
完成數據與視圖的雙向綁定
-
初始化渲染
接下來,咱們來驗證猜測。
注意,到目前爲止,咱們一行源碼都還沒看
驗證遍歷DOM
調用棧中walk
與walkChildren
被調用屢次,大機率他們就是具體遍歷工做執行的方法,讓咱們確認下。
在源碼walk
方法中打上log
:
export const walk = (node: Node, ctx: Context): ChildNode | null | void => { console.log('walk', node); // ... } 複製代碼
排除換行符"\n "
對應的文本節點,打印順序以下:
walk div walk <button>add 1</button> walk "add 1" walk <p>0</p> walk "0" 複製代碼
從打印結果看,這是個深度優先遍歷(若是有子節點就遍歷子節點,沒有子節點就遍歷兄弟節點)
顯然,petite-vue
mount
時採用深度優先遍歷,並對遍歷到的每一個與上下文狀態相關的DOM
節點進行處理。
在Demo
中,上下文包含狀態{count: 0}
:
createApp({count: 0}).mount() 複製代碼
在遍歷後<p>{{count}}</p>
變爲<p>0</p>
。
肯定雙向綁定的粒度
接下來咱們須要確認雙向綁定的做用範圍,即:
觸發更新後,多大範圍的
DOM
會被從新遍歷並執行相應DOM
操做?
打開Performance
後,點擊<button>add 1</button>
觸發更新:
能夠看到,沒有任何walk
、walkChildren
(或相似遍歷過程),只調用了reactiveEffect
一個方法就更新了DOM
。
這意味着mount
時的深度優先遍歷創建了狀態
與更新DOM的方法
之間一一對應的關係。
由於對應關係肯定了,就再也不須要額外的遍歷過程肯定須要變化的DOM
。
當更新狀態
後,只須要找到與他有關係的更新DOM的方法
執行就行。
好比:將count
狀態與以下函數創建聯繫:
function setCount(value) { p.textContent = value; } 複製代碼
每當count
變化後調用setCount(count)
就能更新p
對應DOM
。
因此,petite-vue
的工做原理,主要包括兩點:
-
mount
時深度優先遍歷DOM
,對有狀態的DOM
(好比<p>{{count}}</p>
)創建狀態
與更新DOM的方法
之間一一對應的關係 -
update
時找到該狀態
對應的更新DOM的方法
並執行
能夠看到,即便不深刻源碼,也能大致瞭解工做流程。
若是你想更進一步,好比了解關係是如何創建的(涉及到響應式更新),那麼就須要深刻源碼了。
這裏推薦Vue Mastery
的Vue 3 Reactivity
課程,能夠補齊響應式更新這塊知識。
總結
本文介紹了複雜框架源碼的閱讀辦法 —— 即從抽象到具體。
-
從
mount
時與update
時的調用棧推導出總體工做流程
-
從
總體工做流程
中發現核心知識 —— 響應式更新
當掌握總體工做流程
與響應式更新
後,再閱讀本身感興趣的部分纔不至於陷入龐大的代碼量中。
你,學廢了麼?
最後,創做不易,若是對你們有所幫助,但願你們點贊支持,有什麼問題也能夠在評論區裏討論😄~