最近又抽時間把 vue-next/runtime-core
的源碼陸陸續續地看完了,期間整理了不少筆記,但都是碎片化的。原本是想整理一下,寫成一篇文章分享出來的,可是感受最終的成果物只能是一篇篇幅巨長的解析文,就算我一行一行的把源碼加上註釋,其閱讀體驗也會不好,由於每一個人讀代碼的習慣不一樣,思路不一樣。正所謂拋磚引玉,因此,我覺的寫一篇嚮導文做爲這塊磚應該是足夠了,但願能夠幫助到想看源碼但以爲無從看起、無從下手的讀者。vue
另外一方面,也算是給本身挖一個坑,由於這篇文章中涉及到的不少內容,三言兩語確定是說不清的,這就意味着以後必需要寫其餘文章來填補這些空白。我會盡量的將高內聚的模塊整理到一塊兒,而後再分享出來,儘可能避免陷入羅列代碼的境地,從而提升文章質量吧。node
閱讀筆記我託管在語雀上,不嫌亂的也能夠看這裏。react
工欲善其事,必先利其器,要看源碼,拿寫字板來看確定是不行的(固然也不排除牛人)。你所須要的就是一個支持代碼跳轉的編輯器便可,我用的是 VSCode
,固然了,若是你用 VIM
、Sublime
也是能夠的。typescript
另外還需一些儲備知識:canvas
vue-next
的代碼,而且是 pre-alpha
的版本,這就要求你對以前 vue
有必定的瞭解,若是是第一次接觸,我覺的閱讀源碼的意義也不是很大須要熟練掌握 debug
的基礎技巧和流程,經過 debug
的方式來看代碼有兩個好處小程序
typescript
有必定掌握程度,最起碼給知道 interface
、enum
等概念通常有三種途徑:api
這裏推薦第二種方式,由於單元測試是官方團隊維護的,質量確定有保證,二來單元測試通常都很簡單,同時帶有註釋,這有利於咱們理解代碼。數組
因爲 vue-next
使用 jest
進行單元測試,在 vscode
中安裝 Jest
插件便可,它支持行內 debug lens 快捷入口,方便直接對某條單元測試進行 debug
。緩存
不過要注意配置一個自定義選項:數據結構
"jest.debugCodeLens.showWhenTestStateIn": [ "fail", "unknown", "pass", // 注意這裏 ]
這裏的 "pass"
表明即便單元測試經過,也會在上方顯示 debug
lens,默認狀況下,單元測試用例經過的話,這個 debug
lens 標識不會顯示。
runtime-core
目錄下有多個文件,我暫且把每一個文件都當作一個子模塊來看待。vue
的代碼質量仍是挺好的,模塊與模塊之間的耦合性都不是特別高,正由於如此,基本上每一個模塊都有本身單獨對應的單元測試文件。
我在看的時候,基本上就是挨個看這些模塊的單元測試,而後調試過程當中,會主動的進行一些代碼跳轉,去看一下具體的實現細節。下面把當前最新代碼下該文件目錄下的全部模塊的職能進行一些總結和概括。
有一些較獨立的模塊我尚未看完,可是不影響總體的源碼閱讀進程,往後對這些獨立模塊進行單獨研究時,纔回來補充這些 todo
就行了。
api
相關實現公共 api
的模塊均是以 apixxx
這樣的格式來命名的,以下:
apiApp.ts
: 有 3 個比較重要的接口須要看一下,App
、AppConfig
和 AppContext
,若是對於 vue2
比較熟悉的話,會很容易理解。createApp
是一個工廠方法,返回一個符合 App
接口約束的對象,其內部方法會與一個符合 AppContext
接口約束的對象進行交互。apiCreateComponent.ts
: 這個文件內部包含多個對於 createComponent
函數簽名的重載聲明,其存在目的應該是爲了幫助 ts 提供更好的類型推斷以提高開發體驗。apiInject.ts
: 組件依賴注入 feature
的實現邏輯,實現方式很簡單,直接與 component
文件中暴露的 currentInstance
變量進行交互,實現繼承、賦值、取值等邏輯apiLifecycle.ts
: 新的組件聲明週期 hooks
,主要看 injectHook
方法就能夠了,這裏的 target
默認狀況下指向 currentInstance
,以後會在將某個回調邏輯緩存在 currentInstance
實例的聲明週期回調函數數組中apiOptions.ts
:其中包含對於 component
如何解析 options
的實現邏輯,代碼比較長同時也比較複雜,耦合性與其餘幾個文件較高。但其實沒有必要直接看完它內部的所有代碼,由於 options
中每一段的解析邏輯互相之間都是獨立的,所以能夠專門針對某個 option
單獨去看它內部的解析邏輯,我目前只看了 data
以及 lifecycle
。apiReactivity.ts
:就是對 reactivity
包中的 api
的從新導出,沒有什麼額外的東西apiWatch.ts
: 暫時還沒仔細看,不過根據名字可知是和 watch
相關的 api
,粗略的看了一下,發現耦合性比較低,所以能夠往後再看component.ts
: 主要包含如何建立一個內部組件實例的邏輯,代碼比較長,可是點進去看的話,會發現它實際上是在調用其餘模塊的暴露的 api,自己的邏輯仍是比較簡單的。須要注意的是,這個文件會暴露一對 setCurrentInstance
和 getCurrentInstance
方法用來維護 currentInstance
變量的指向,同時它會在別的模塊中被使用到componentProxy.ts
: 聲明瞭 render proxy
的實現邏輯,這個 proxy
主要負責外部如何與內部組件實例進行交互,能夠將它看作是一個外部組件實例componentProps.ts
: 主要看 resolveProps
,實現瞭如何解析各類形式的 props
componentSlots.ts
:主要看 resolveChildren
,實現瞭如何解析各類形式的 children
節點componentRendererUtils.ts
: 一些渲染組件的 util
方法,按名字瞭解各個方法的含義便可createRenderer.ts
:這個和其餘文件耦合度較低,能夠理解爲 VNode
的渲染器,只要實現了其接口,能夠在任何上下文環境中進行渲染,好比小程序、native
、canvas
或者內存環境,關於如何編寫一個 renderer
,直接看 runtime-test
或者 runtime-dom
的代碼便可directives.ts
: 指令相關的內部 api
,當前的代碼版本,這部分可能不少 todo
所以能夠往後再回來看看errorHandling.ts
: 錯誤處理相關,暫時還沒仔細看scheduler.ts
: 做業調度器相關,暫時還沒仔細看shapeFlags.ts
: 組件自己和 children
類型的枚舉聲明及常量suspense.ts
: suspense
相關,暫時還沒看,對於其餘文件中的 suspense
的相關邏輯,我徹底是按照 react
中相關概念來理解的,暫時沒遇到任何障礙warning.ts
: 警告相關,大部分是一些 util 方法,按名字理解其含義就行了直接說我本身的閱讀順序,我認爲仍是比較符合認知習慣的:
vnode.ts
和 h.ts
等關於 vdom
的代碼瞭解一下新的 VNode
的數據結構apiApp.ts
,看掛載過程是怎樣把 VNode
和渲染上下文關聯起來的,這個過程當中天然會涉及到各類 apixxx.ts
中的內容,挨個看就行了api
,須要瞭解實現細節的話,要進一步看 component.ts
,其中主要包含內部組件實例的數據結構以及建立流程,一樣地,打斷點一行一行讀便可期間會遇到 suspense
、lifecycle
之類的代碼,這類代碼也能夠當作單獨的內容進行閱讀,在一開始看的時候,也能夠不要太糾結於細節,當對總體流程有一個大概瞭解以後再回頭來看會清晰不少,以後我會專門整理一篇文章介紹這塊是如何實現的。
雖然 vue-next
的代碼如今還處在初期的階段,可是總體的閱讀體驗仍是不錯的,結構清晰,可讀性也比較高,一些關鍵模塊也有註釋進行說明,惟一不足的地方在於,不少地方仍是藉助 as
關鍵字來進行類型斷言,我以爲這些地方可能有更好的方式實現類型推斷吧。
關注 全棧_101,只談技術,不談人生
另:接各類規模全棧外包項目,有意者私聊