預計今年發佈的Vue3.0到底有什麼不一樣的地方?

-w949

還有幾個月距離vue2的首次發佈就滿3年了,而vue的作者尤雨溪也在去年年末發佈了關於vue3.0的計劃,如果不出意外,我們將在今年的某個時間點見證Vue3.0的發佈,雖然前幾天在《StateOfJS: 2018年JavaScript生態圈趨勢報告》一文中我們看到目前Vue的使用者比React還少了不少,但在Github上Vue的star數已經超越React,可見用戶對Vue的喜愛,那即將發佈的Vue3又有什麼新特性呢?我們一起來看看吧!

Vue 3.0 已經在原型設計階段了,而且我們已經實現了一個與 2.0 的特性近乎相等的運行時了。下文中列出的許多條目,要麼已經實現了,要麼已經確認可實現。那些還未實現或者仍在探索階段的條目會用一個“*”標記

-w1159

性能提升

一句話簡介:更小巧,更快速;支持搖樹優化;支持 Fragments 和跨組件渲染;支持自定義渲染器。
  • 更小巧:這份新的代碼庫在設計之初就考慮到了對“搖樹優化 (tree-shaking)”的友好。那些如內置組件 (<transition><keep-alive>) 、運行時工具性指令(v-model)等特性將變爲按需導入,所以也是“可搖樹的”。對於這個新的運行時,它的大小將永遠保持在 10kb 之下。另外,使這些特性變爲“可搖樹的”後,我們就可以提供更多的內置特性,同時還不會增加網絡負載——如果沒使用到這些特性的話。

搖樹優化,是一種在打包時去除沒用到的代碼的優化手段,谷歌有一篇教程可以瞭解下: Reduce JavaScript Payloads with Tree Shaking

  • 更快:在前期的基準測試中,我們看到整體性能有了一倍的提升,包括虛擬DOM的掛載和打補丁(patching,指更新——譯註) 的速度(我們從 Inferno 那裏學了好些個技巧過來——Inferno 是目前速度最快的虛擬DOM實現),以及組件實例化速度和數據監測的性能。在 3.0 中,你應用的啓動時間將縮減一半。
  • 支持 Fragments 和 Portal:雖然體積更小了,但 3.0 還將內置對 Fragments (即允許組件擁有多個根節點) 和 Portal (即允許在 DOM 的其他位置進行渲染,而不是組件內部) 的支持。

關於 Portal ,你可以將其理解爲跨組件渲染或者異地渲染,vue-portal 是一個第三方實現,可以瞭解一下;Fragments 特性也有一個第三方庫,但譯者認爲這個庫的內部實現不夠完善,叫做 vue-fragments,感興趣可以瞭解一下。

  • 增強的 slot 機制:所有由編譯器生成的 slot 都將是函數形式,並且在子組件的 render 函數被調用過程中才被調用 (譯註:現在只有 scoped slot 纔是函數形式,其渲染的時機也是在父組件的渲染進行時)。這使得 slot 中的依賴項 (即數據——譯註) 將被作爲子組件的依賴項,而不是現在的父組件;從而意味着:1)當 slot 的內容發生變動時,只有子組件會被重新渲染;2)當父組件重新渲染時,如果子組件的內容未發生變動,子組件就沒必要重新渲染。這種機制的改變,可以提供更精確的變動探測,也就可以消除沒必要的重渲染。
  • 支持自定義渲染器 (Renderer):這個 API 可以用來創建自定義的渲染器,它將作爲“一等公民”出現,到時不再需要 fork 一份 Vue 的代碼來通過修改實現自定義。這個 API 的到來,將使得那些如 Weex 和 NativeScript 的“渲染爲原生應用”的項目保持與 Vue 的同步更新變得更加容易。除此之外,還將使得那些爲了各種用途而創建自定義渲染器變得極其容易。

編譯器相關的提升 *

  • 如果採用的是支持“搖樹優化”的打包器,模板中使用到的那些可選特性,在生成的代碼中將通過 ES 的模塊語法導入;而在打包後的文件中,那些沒用到的可選特性就會被“搖掉”。
  • 由於新的虛擬 DOM 實現所帶來的提升,我們可以執行一些更加高效的編譯耗時優化,如靜態樹提升(static tree hoisting)、靜態屬性提升(static props hoisting);以及爲運行時提供一些來自編譯器的提示,以此避開子組件的規範過程 (children normalization);提供 VNode 快速創建路徑; 等等。
  • 我們計劃對解析器進行重寫,以便在對模板進行編譯發生錯誤時,可以提供錯誤發生的位置信息;除此之外還可以帶來對模板的 source map 支持;還可以支持第三方工具如 eslint-plugin-vue 和 IDE 的語言服務 (language services) 特性。

API 變動

一句話介紹:除渲染函數 API 和 scoped-slot 語法之外,其餘均保持不變或者將通過另外構建一個兼容包來兼容 2.x。
  • 模板語法的 99% 將保持不變。除了 scoped slot 語法可能會有一些微調之外,我們還沒有任何其他針對模板的變動計劃。
  • 3.0 版本將原生地支持基於 class 的組件,而且無需藉助任何編譯及各種 stage 階段的特性,以此提供良好的編寫體驗。許多現有的 (組件) 配置項將有對應的合理的 class 版本的 API。各種 stage 階段的特性,如 class 的靜態字段和裝飾器 (decorator) 等仍然可以選擇性地使用,以此增強編寫體驗。另外,整體的 API 在設計時也將考慮 TypeScript 的類型推斷特性。3.x 的代碼庫本身將用 TypeScript 來編寫,並提供增強的 TypeScript 支持。(就是說,TypeScript 的使用與否仍然是整體可選的)
  • 2.x 系列的基於對象的組件格式仍將受支持,不過會在內部將其轉換爲一個相應的 class。
  • 仍然支持 Mixins。*
  • 爲了避免在安裝插件時造成對 Vue 的運行時的修改,頂層 API 可能會做一個大的翻修。到時,插件的作用域將只侷限到具體的一個組件樹,使得對那些依賴於某些具體插件的組件的測試變得容易,也會使得在同一個頁面中掛載多個使用不同插件——但使用同一個 Vue 運行時——的 Vue 應用變爲可能。*
  • 函數式組件將支持純函數的書寫形式——不過,這樣的話異步組件就需要通過一個輔助性函數來顯式地創建了。
  • 變動最大的部分將是渲染函數 (render) 中的虛擬DOM的格式。我們現在正在收集主流的第三方庫的作者們的反饋,在對這些變動有了更多的信心之後,我們還會將更多的細節曝光;雖然變動較大,但是隻要你沒在你的應用中重度使用手寫的渲染函數 (不是指 JSX),那麼變動之後的升級應該會比較容易。

代碼重構

一句話介紹:更優良的內部模塊解耦;TypeScript;更易於貢獻的代碼庫。

在從零開始編寫 3.0 之初,“達到更加清晰和更易維護的架構,特別是爲了讓代碼的貢獻變得容易”就是我們的目標。爲了對複雜性進行隔離,我們將一些內部功能拆分爲了多個單獨的包。例如,observer 模塊將成爲一個單獨的包,擁有自己對外的 API 和自己的測試用例;不過請注意,這不會對框架級的 API 造成影響——你不需要另外手動從多個包裏導入許多小件小件的模塊就可以使用 Vue,相反 Vue 的最終包會事先裝配好這些內部包。

另外,代碼庫現在改爲了用 TypeScript 編寫;雖然這會使得“熟練TypeScript”成爲對新代碼庫進行貢獻的一個前置要求,不過我們相信有類型信息配合 IDE 的支持,對於一個新的貢獻者來說,要做出有意義的貢獻,實際上反而會更加容易。

將 observer 和 scheduler 解耦爲分開的兩個包後,我們還可以拿一些替代的實現對這兩個包進行置換試驗。例如,我們可以實現一個兼容 IE11、API 也相同的 observer;或者實現另外一種利用 requestIdleCallback 來在長耗時的更新中產出工作成果到瀏覽器的 scheduler。

重寫虛擬DOM (Virtual DOM Rewrite)

隨着虛擬 DOM 重寫,我們可以期待更多的 編譯時(compile-time)提示來減少 運行時(runtime)開銷。重寫將包括更有效的代碼來創建虛擬節點。

優化插槽生成(Optimized Slots Generation)

在當前的 Vue 版本中,當父組件重新渲染時,其子組件也必須重新渲染(11月20日更新:這句話是不嚴謹的,非常容易產生誤導,我覺得有必要說明一下: 2.0 組件的重新渲染就是組件粒度的,除非修改的數據是子組件的 props,纔會觸發子組件的重新渲染。引用自:https://juejin.im/pin/5bf28dd...)。 使用 Vue 3 ,可以單獨重新渲染父組件和子組件。

靜態樹提升(Static Tree Hoisting)

使用靜態樹提升,這意味着 Vue 3 的編譯器將能夠檢測到什麼是靜態組件,然後將其提升,從而降低了渲染成本。它將能夠跳過未整個樹結構打補丁的過程。

靜態屬性提升(Static Props Hoisting)

此外,我們可以期待靜態屬性提升,其中 Vue 3 將跳過不會改變節點的打補丁過程。

基於 Proxy 的觀察者機制

目前,Vue 的反應系統是使用 Object.defineProperty 的 getter 和 setter。 但是,Vue 3 將使用 ES2015 Proxy 作爲其觀察者機制。 這消除了以前存在的警告,使速度加倍,並節省了一半的內存開銷。

爲了繼續支持 IE11,Vue 3 將發佈一個支持舊觀察者機制和新 Proxy 版本的構建。

兼容 IE 11 *

一句話介紹:IE 11 將受到支持,但將會是另外構建一個版本 (build) 的形式支持,不過這個版本會存在與 Vue 2.x 響應式機制所存在的同樣的侷限。

新的代碼庫目前只針對主流瀏覽器,而且我們假定他們都支持 ES2015。但是,哎,我們也知道在可預見的未來還有很多用戶仍然需要支持 IE11。除了 Proxy 外,大多數 ES2015 的特性都可以用轉譯或者墊片的方式在 IE11 中使用。我們的計劃是另外單獨實現一個具有同樣 API 的替代性 observer,不過是基於老式的 Object.defineProperty API;然後再通過單獨構建一個使用這個實現的 Vue 3.x 版本 (build) 進行發佈,不過這個單獨的版本還是會有 Vue 2.x 在變動探測方面所存在的問題,所以它其實並不是一個完全兼容 3.x 的一個版本。我們也意識到這會給第三方庫的作者們帶來某些不便,因爲他們需要考慮兩個不同版本之間的兼容性問題,不過當我們真的推進到那個階段時,那時我們肯定會確保提供一份清晰的指導。

監測機制

一句話介紹:更加全面、精準、高效;更具可調試性的響應跟蹤;以及可用來創建響應式對象的 API。

3.0 將帶來一個基於 Proxy 的 observer 實現,它可以提供覆蓋語言 (JavaScript——譯註) 全範圍的響應式能力,消除了當前 Vue 2 系列中基於 Object.defineProperty 所存在的一些侷限,如:

  • 對屬性的添加、刪除動作的監測
  • 對數組基於下標的修改、對於 .length 修改的監測
  • 對 Map、Set、WeakMap 和 WeakSet 的支持

另外這個新的 observer 還有以下特性:

  • 公開的用於創建 observable (即響應式對象——譯註) 的 API。這爲小型到中型的應用提供了一種輕量級的、極其簡單的跨組件狀態管理解決方案。(譯註:在這之前我們可以通過另外 new Vue({data : {...}}) 來創建這裏所謂的 observable;另外,其實 vuex 內部也是用這種方式來實現的)
  • 默認爲惰性監測(Lazy Observation)。在 2.x 版本中,任何響應式數據,不管它的大小如何,都會在啓動的時候被監測。如果你的數據量很大的話,在應用啓動的時候,這就可能造成可觀的性能消耗。而在 3.x 版本中,只有應用的初始可見部分所用到的數據會被監測,更不用說這種監測方案本身其實也是更加快的。
  • 更精準的變動通知。舉個例子:在 2.x 系列中,通過 Vue.set 強制添加一個新的屬性,將導致所有依賴於這個對象的 watch 函數都會被執行一次;而在 3.x 中,只有依賴於這個具體屬性的 watch 函數會被通知到。
  • 不可變監測對象(Immutable observable):我們可以創建一個對象的“不可變”版本,以此來阻止對他的修改——包括他的嵌套屬性,除非系統內部臨時解除了這個限制。這種機制可以用來凍結傳遞到組件屬性上的對象和處在 mutation 範圍外的 Vuex 狀態樹。
  • 更良好的可調試能力:通過使用新增的 renderTracked 和 renderTriggered 鉤子,我們可以精確地追蹤到一個組件發生重渲染的觸發時機和完成時機,及其原因。

發佈時間

不必太過擔心,至少還能緩半年。

參考來源:
Plans for the Next Iteration of Vue.js
[[譯] 尤雨溪:Vue 3.0 計劃](https://juejin.im/post/5bb719...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章