前言
vue 3.0 源碼剛出沒多久 本人日常開發慣用vue 以前看過 vue 2.0 的一些源碼 此次準備作一次逐行分析 3.0 的源碼 歡迎你們在下方留言 你們一塊兒討論。javascript
vue 3.0 源碼特點:
- 結構清晰
經過yarn的工做區方式,簡單來講就是功能模塊按照package.json下的workspace字段,解耦劃分紅一個個文件夾(自帶package.json,不懂的跳轉:yarn 文檔),每一個功能能夠本身 yarn dev 編譯出相應模塊文件,換句話說 vue 3.0 的響應式模塊 徹底能夠抽離出來用做其餘項目 這是以前vue 2.0 作不到的
- Typescript重構
以前vue 2.0 是用 Flow 來作靜態類型代碼檢查,後面發現這個團隊不靠譜 Flow項目爛尾了,根本拼不過微軟大大的TS,如今TS的前端市場佔比也很高,所以本次也是直接狠下心用Typescript重構了。
以前本人有個項目用了vue+TS,但總以爲本身的使用很初級,高階使用 如範型之類的,都沒有落地接觸過,這個源碼中有很是多的TS最佳實踐,高階TS使用。因此看這個源碼還能同時很好地學習 TS ,一箭雙鵰。
- Proxy改造
看過2.0源碼的或者稍微瞭解過vue響應式原理的都知道2.0使用的是Object.defineProperty作數據劫持的。此次也是直接改形成Proxy(ES6語法),性能不像Object.defineProperty須要一上來就遍歷全部,性能更加優異,下面會繼續討論這塊的。
vue 3.0 源碼如何有效地看呢:
- 必看
主目錄的package.json,每一個項目應該首先看這個文件。由於它可讓咱們瞭解源碼支持哪些scripts,好比 test 咱們能夠yarn test跑一下測試腳本試試。workspace字段表明工做區的內容即功能模塊代碼位置,就很少說了。
還有一些前端工程化發佈流程相關的加餐知識,學到了也能夠應用到本身的項目中,這塊能夠下節附贈給你們。
- 先關注某個功能模塊的主流程
前面說了 workspace 的概念,咱們能夠從其中一個功能模塊開始,看主流程文件,中間遇到函數回調,先看字面意思,看完主流程再去一個個切進去深刻看。如:先從 reactivity 文件夾下的 reactive.ts 響應式主流程看起。
- 語法文檔
由於有不少 TS / ES6 的語法,建議配合着 TS 文檔及 ES6 語法來看,遇到不會的語法趕忙查
- yarn dev
調試源碼,編譯生成相應文件,本身寫一個html引入來測試,這塊下節給你們說一下
正文
先看這塊,我將源碼的註釋翻譯了一下,感受仍是不夠立體,須要品味一番
html
語法上看,用到了 TS 的範型接口的概念
- 什麼是泛型,這是一種 OOP 後端語言經常使用的概念,即下圖中的<T>,能夠從字面的意思推導出: 泛指的,不肯定的類型。傳進來什麼類型後續就用什麼類型,好比這裏Set若是傳入Number類型,add方法的入參也必須是Number類型
- 爲何說是接口,由於 TS 核心對 ES6 的 Set Map WeakSet WeakMap都作了封裝 寫入 TS 聲明文件(.d.ts),這樣 TS 就能對這些類型進行類型推斷,靜態檢查
語義上看,主要是爲了構造 targetMap 這個存儲依賴關係的WeakMap 這裏用WeakMap的緣由在於,WeakMap鍵名所引用的對象都是弱引用,即垃圾回收機制不將該引用考慮在內,不影響引用計數,只要其餘引用都清除,垃圾回收自動回收掉該對象內存,正好適合該場景:你須要存儲proxy化的target對象,一旦其餘target對象引用清除,這邊targetMap也須要自動清除該對象,有助於防止內存泄漏。
目的就是爲了構造出下方這種格式,具體 Dep 的泛型 ReactiveEffect 是什麼須要到 effect.ts再看,如今關注這個結構。
{
target:{
key: Dep
}
}
複製代碼
再看下一塊 前端
這邊源碼註釋翻譯就是這4個weakmap存儲着原始數據到觀察者的映射 這裏注意這個<->符號表明的是雙向的,即原始數據 -> 觀察者,觀察者 -> 原始數據。
這邊爲何要存儲雙向的,應該仍是從
經過犧牲空間複雜度來換取更高效的時間複雜度考慮,由於這樣存儲獲取的時間複雜度是O(1),而且還能得到一些其他的好處好比一些自帶的性能極佳的方法
這邊主要是作了一些預備操做,好比聲明集合的類型,正則表達式等,以及是否可觀察的函數,這邊我已經註釋了,對主流程沒有太大影響。
接下來屬於核心流程
vue
對外暴露的reactive方法是proxy化,這邊對只讀數據進行了特殊處理readonly函數,這裏還須要對值作判斷,若是這個值是響應式的proxy直接返回響應式版本。其實最後的核心proxy化步驟都是createReactiveObject這個函數
這邊是proxy化的核心流程,其實看着仍是比較簡單,主要是proxy的handler這一塊下一節會深刻進去。
最後是一些對外暴露的函數,字面意思應該都看得懂,這裏注意獲取原始數據這裏,最後直接或操做符了observed,有兩種可能,一種是非可觀察的白名單即上文所提到的,一種是基本數據類型
尾言
這節主要講了響應式的核心文件及主流程,內容並不複雜,有問題能夠下方留言,互相討論。下節會深刻到文件effect.ts,這塊也是源碼中理解的難點,而且會附送源碼中的一些工程化的實踐。java