摘要: Vue 3.0預覽。vue
Fundebug經受權轉載,版權歸原做者全部。vuex
還有幾個月距離 vue2 的首次發佈就滿 3 年了,而 vue 的做者尤雨溪也在去年年底發佈了關於 vue3.0 的計劃,若是不出意外,咱們將在今年的某個時間點見證 Vue3.0 的發佈,雖然前幾天在《StateOfJS: 2018 年 JavaScript 生態圈趨勢報告》一文中咱們看到目前 Vue 的使用者比 React 還少了很多,但在 Github 上 Vue 的 star 數已經超越 React,可見用戶對 Vue 的喜好,那即將發佈的 Vue3 又有什麼新特性呢?咱們一塊兒來看看吧!數組
Vue 3.0 已經在原型設計階段了,並且咱們已經實現了一個與 2.0 的特性近乎相等的運行時了。下文中列出的許多條目,要麼已經實現了,要麼已經確承認實現。那些還未實現或者仍在探索階段的條目會用一個「*」標記瀏覽器
性能提高
一句話簡介:更小巧,更快速;支持搖樹優化;支持 Fragments 和跨組件渲染;支持自定義渲染器。網絡
- 更小巧:這份新的代碼庫在設計之初就考慮到了對「搖樹優化 (tree-shaking)」的友好。那些如內置組件 (、) 、運行時工具性指令(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 解耦爲分開的兩個包後,咱們還能夠拿一些替代的實現對這兩個包進行置換試驗。例如,咱們能夠實現一個兼容 IE十一、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/5bf28ddd6fb9a056783705fc)。 使用 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 計劃