Vue 2.6 釋出:新語法、效能改進、向 3.0 看齊

weixin_34185364發表於2019-02-13
13437285-f4f74621ef043488.png

近日,尤雨溪在 medium 上宣佈推出 Vue 2.6——代號“Macross”。尤雨溪表示,在過去的一年中,他們在開發新 CLI 和 3.0 原型設計上花了很多時間。因此,Vue core 2.x 在很長一段時間內都沒有推出重大更新。現在是時候了,2.6 版本帶來了一些實質性的改進、內部變更和新功能,本文將會重點介紹。

如果需要了解完整的詳細資訊,請務必檢視 GitHub 上的發行說明

slot:新語法、效能改進、向 3.0 看齊

slot 是在 Vue 中靈活組合元件的一種重要機制。在 3.0 版本原型設計過程中,我們發現了很多可以改進它的方法。其中一些不會帶來重大變更,可以在 2.x 的次要版本中釋出。對於那些需要做出重大變更的,我們也在努力嘗試在 2.x 版本中提供漸進式的替代方案,讓將來的遷移變得更容易些。

新語法

首先是 scoped slot 的新語法。我們提出、討論並試驗了多種不同的設計:

最終確定了這個 RFC 所描述的v-slot 語法

以下是使用命名 slot 的一個簡短示例:

複製程式碼

<my-component>  <template v-slot:header>    <p>Header</p>  </template>    <template v-slot:item="{ data }">    <h2>{{ data.title }}</h2>    <p>{{ data.text }}</p>  </template>    <template v-slot:footer>    <p>Footer</p>  </template></my-component>

使用了多個命名 slot 的元件的 v-slot 用法。

新語法通過單個指令使用普通的 slot 和 scoped slot,並強制要求使用更明確和具有更高可讀性的命名 slot。它與現有語法完全相容,馬上就可以在 2.6 中釋出。

如果你已熟悉現有的 slot 語法,我們建議你閱讀一下這個 RFC,以更好地理解新語法背後的基本原理

如果你對 slot 還不熟悉,建議先檢視一下更新的slot 文件

效能改進

我們將在 3.0 版本中看到有關 slot 的另一個改進,即普通 slot 和 scoped slot 的實現將得到統一,主要是因為 scoped slot 在效能方面的優勢。普通 slot 將在父元件的渲染週期中渲染。當 slot 的依賴項發生變化時,會導致父元件和子元件進行重新渲染。另一方面,scoped slot 被編譯成​​行內函數,並在子元件的渲染週期中被呼叫。

這意味著子元件將會收集 scoped slot 所依賴的所有資料依賴項,從而做出更精確的更新。在 2.6 版本中,我們引入了一種優化手段,進一步確保父元件的依賴項變化僅影響到父元件,並且如果只使用了 scoped slot,就不會強制子元件做出更新。

此外:

  • 所有使用新 v-slot 語法的 slot 都將被編譯為 scoped slot,這意味著所有使用新語法的 slot 都會自動獲得效能提升;

  • 現在所有普通的 slot 也通過this.$scopedSlots暴露出來,這意味著使用 render 函式而不是模板的使用者現在也可以使用 this.$scopedSlots,而不用擔心傳入的 slot 是什麼型別。

在 3.0 中,將不再區分 scoped 與非 scoped slot——所有 slot 將使用統一的語法,被編譯為相同的格式,並具有相同的效能。

非同步錯誤處理

Vue 的內建錯誤處理機制(元件內 errorCaptured hook 和全域性 errorHandler hook)現在也會捕獲 v-on 處理程式內部的錯誤。此外,如果任意一個生命週期 hook 或事件處理程式執行了非同步操作,現在可以從函式中返回一個 Promise,Promise 鏈中任何一個未被捕獲的錯誤都會被髮送給錯誤處理程式。如果使用了 async/await,則會變得更加容易,因為非同步函式隱式返回 Promise:

複製程式碼

export default {  async mounted() {    // if an async error is thrown here, it now will get    // caught by errorCaptured and Vue.config.errorHandler    this.posts = await api.getPosts()  }}

動態指令引數

指令引數現在可以接受動態 JavaScript 表示式:

複製程式碼

<div v-bind:[attr]="value"></div><div :[attr]="value"></div> <button v-on:[event]="handler"></button><button @[event]="handler"></button> <my-component>  <template v-slot:[slotName]>    Dynamic slot name  </template></my-component>

更多細節可以在這個 RFC中找到。

為了方便起見,如果引數值為 null,則繫結和監聽器會被移除。庫的作者要注意:這個功能要求 Vue 執行時為 2.6.0 及以上版本。如果你提供預編譯的元件,並希望保持與 2.6 之前版本的相容性,請避免在原始碼中使用它。

編譯器警告訊息中的程式碼幀

這要感謝 GitHub 使用者 @gzzhanghao 提出的拉取請求

從 2.6 版本開始,大多數模板編譯警告訊息現在都帶有原始碼區間資訊。這樣我們就能夠為這些警告訊息生成更好的程式碼幀:

[圖片上傳中...(image-5c3e53-1550064792001-0)]

顯式建立單獨的反應式物件

2.6 版本引入了一個新的全域性 API 來顯式建立單獨的反應式物件:

複製程式碼

const reactiveState = Vue.observable({  count: 0})

生成的物件可以直接用在計算屬性或 render 函式中,並在發生變化時觸發適當的更新。

伺服器端渲染期間的資料預取

新的serverPrefetch hook允許任何元件(不僅僅是路由級別的元件)在伺服器端渲染期間預取資料,使使用更加靈活,並降低資料獲取和路由器之間的耦合。一些專案(如 Nuxt 和 vue-apollo)已經計劃通過這個新功能來簡化它們的實現。

新 ES 模組構建,可直接匯入使用

之前,我們的 ES 模組構建主要目標是與捆綁包一起使用。這些構建包含了在編譯時需要替換為環境變數的內容。Vue 2.6 現在提供了新的 ES 模組構建,目標是直接在瀏覽器中使用:

複製程式碼

<script type="module">import Vue from 'https://unpkg.com/vue/dist/vue.esm.browser.js'  new Vue({  // ...})</script>

重要的內部變更

讓 nextTick 恢復使用 Microtask

在 2.5.0 版本中,我們做出了一個內部調整,如果更新是在 v-on 事件處理程式中觸發的,則會導致 nextTick 使用 Macrotask(而不是 Microtask)來讓更新進入佇列。最初這麼做是為了修復一些瀏覽器的邊界情況,但反過來又導致了很多其他問題。在 2.6 版本中,我們為原始問題找到了一個更簡單的修復方案,這樣我們就可以在任何情況下恢復 nextTick 使用 Microtask。

如果你對這方面的技術細節感興趣,請在此處檢視。

通過 this.$scopedSlots 暴露的函式現在總是返回 Arrays

這個變更隻影響 render 函式使用者。在 render 函式中,scoped slot 通過 this.$scopedSlots 暴露為函式。到目前為止,呼叫 scoped slot 函式可能返回單個 VNode 或 VNode 陣列,具體取決於父元件傳入的是什麼。這種設計實際上是一種疏忽,因為它返回的值型別是不確定的,並且可能會導致意外的邊界情況。

在 2.6 版本中,scoped slot 函式確保只返回 VNode 陣列或 undefined。已有程式碼中如果有些地方返回的是陣列,但沒有被檢查出來,可能會出問題。更多細節請看這裡

感謝

感謝在這一版本中提供拉取請求的貢獻者們,以及參與 RFC 討論的所有社群成員。

(本文章轉載自infoq, 如有侵權, 請聯絡作者刪除)

相關文章