一文看懂Vue3.0的優化

小磊哥er發表於2020-10-16

1.原始碼優化:

a.使用monorepo來管理原始碼

  • Vue.js 2.x 的原始碼託管在 src 目錄,然後依據功能拆分出了 compiler(模板編譯的相關程式碼)、core(與平臺無關的通用執行時程式碼)、platforms(平臺專有程式碼)、server(服務端渲染的相關程式碼)、sfc(.vue 單檔案解析相關程式碼)、shared(共享工具程式碼)等目錄。

  • Vue.js 3.0,整個原始碼是通過 monorepo 的方式維護的,根據功能將不同的模組拆分到 packages 目錄下面不同的子目錄中,每個 package 有各自的 API、型別定義和測試。

b.使用Typescript來開發原始碼

  • Vue.js 2.x 選用 Flow 做型別檢查,來避免一些因型別問題導致的錯誤,但是 Flow 對於一些複雜場景型別的檢查,支援得並不好。

  • Vue.js 3.0 拋棄了 Flow ,使用 TypeScript 重構了整個專案。 TypeScript 提供了更好的型別檢查,能支援複雜的型別推導;由於原始碼就使用 TypeScript 編寫,也省去了單獨維護 d.ts 檔案的麻煩。

2.效能優化:

a.引入tree-shaking的技術

  • tree-shaking 依賴 ES2015 模組語法的靜態結構(即 import 和 export),通過編譯階段的靜態分析,找到沒有引入的模組並打上標記。像我們在專案中沒有引入 Transition、KeepAlive 等不常用的元件,那麼它們對應的程式碼就不會打包進去。

b.移除了一些冷門的feature

  • Vue.js 3.0 相容了 Vue.js 2.x 絕大部分的api,但還是移除了一些比較冷門的feature:如 keyCode 支援作為 v-on 的修飾符、$on,$off 和 $once 例項方法、filter過濾、內聯模板等。

3.響應式實現優化:

a.改用proxy api做資料劫持

  • Vue.js 2.x 內部是通過 Object.defineProperty 這個 API 去劫持資料的 getter 和 setter 來實現響應式的。這個 API 有一些缺陷,它必須預先知道要攔截的 key 是什麼,所以它並不能檢測物件屬性的新增和刪除。

  • Vue.js 3.0 使用了 Proxy API 做資料劫持,它劫持的是整個物件,自然對於物件的屬性的增加和刪除都能檢測到。

b.響應式是惰性的

  • 在 Vue.js 2.x 中,對於一個深層屬性巢狀的物件,要劫持它內部深層次的變化,就需要遞迴遍歷這個物件,執行 Object.defineProperty 把每一層物件資料都變成響應式的,這無疑會有很大的效能消耗。

  • 在 Vue.js 3.0 中,使用 Proxy API 並不能監聽到物件內部深層次的屬性變化,因此它的處理方式是在 getter 中去遞迴響應式,這樣的好處是真正訪問到的內部屬性才會變成響應式,簡單的可以說是按需實現響應式,就沒有那麼大的效能消耗。

4.編譯優化:

a.生成block tree

  • Vue.js 2.x 的資料更新並觸發重新渲染的粒度是元件級的,單個元件內部需要遍歷該元件的整個 vnode 樹。

  • Vue.js 3.0 做到了通過編譯階段對靜態模板的分析,編譯生成了 Block tree。Block tree 是一個將模版基於動態節點指令切割的巢狀區塊,每個區塊內部的節點結構是固定的。每個區塊只需要追蹤自身包含的動態節點。

b.slot編譯優化

  • Vue.js 2.x 中,如果有一個元件傳入了slot,那麼每次父元件更新的時候,會強制使子元件update,造成效能的浪費。

  • Vue.js 3.0 優化了slot的生成,使得非動態slot中屬性的更新只會觸發子元件的更新。動態slot指的是在slot上面使用v-if,v-for,動態slot名字等會導致slot產生執行時動態變化但是又無法被子元件track的操作。

c.diff演算法優化

語法api優化

a.優化邏輯組織

  • 使用 Vue.js 2.x 編寫元件本質就是在編寫一個“包含了描述元件選項的物件”,可以把它稱為 Options API。我們按照 data、props、methods、computed 這些不同的選項來書寫對應的程式碼。這種方式對於小型的元件可能程式碼還能一目瞭然,但對於大型元件要修改一個邏輯點,可能就需要在單個檔案中不斷上下切換和尋找邏輯程式碼。

  • Vue.js 3.0 提供了一種新的 API:Composition API,它有一個很好的機制去解決這樣的問題,就是將某個邏輯關注點相關的程式碼全都放在一個函式裡,這樣在修改一個邏輯時,只需要改那一塊的程式碼了。

b.優化邏輯複用

  • 在 Vue.js 2.x 中,我們一般會用 mixins 去複用邏輯。當抽離並引用了大量的mixins,你就會發現兩個不可避免的問題:命名衝突和資料來源不清晰。

  • Vue.js 3.0 設計的 Composition API,在邏輯複用方面就會很有優勢了。

相關文章