vue 3.x新特性

【知乎 - Vue Function-based API RFC】https://zhuanlan.zhihu.com/p/68477600

【 vuejs/composition-api - api文檔】https://vue-composition-api-rfc.netlify.com/#summary

【github - vuejs/composition-api】https://github.com/vuejs/composition-api

 

根據 vue 作者尤雨溪去年發佈的 vue 3.0 開發路線,vue 3.0 很可能在 2019 年下半年與大家見面。

與此同時,今年下半年初,Vue 團隊先後對外發布了 vue-function-api 和 vue-compisition-api 的 RFC,供開發者提前體驗 vue 3.0 的新特性,並且希望通過這些預覽版的 API,來徵求廣大開發者的意見與反饋,從而爲 vue 3.0 的後續開發和落地打下堅實與穩定的基礎。

一、vue3.0將從頭開始重寫

2018年9 月 30 日,尤雨溪在 medium 個人博客上發佈了 Vue 3.0 的開發路線,我們不妨看看 Vue 3.0 將會有怎樣的發展。

兼容

按照尤雨溪的說法,因爲 Vue 3.0 是主要版本,所以會包含一些重大變更。不過,開發組會非常重視兼容性問題,他們也將盡快開始傳達這些重大變更,並做了這樣的保證:除了渲染函數 API 和作用域插槽語法之外的所有內容都將保持不變,或者通過兼容性構建讓其與 2.x 保持兼容。

總的來說,Vue 3.0 雖然會對頂級 API 進行重大的修整,但依然會保持與 2.x 的兼容。此外,2.x 的最後一個次要版本將成爲 LTS,並在 3.0 發佈後繼續享受 18 個月的 bug 和安全修復更新。

重構

爲了實現更清晰、更易維護的源代碼架構,尤雨溪表示將從頭開始重寫 3.0,並將一些內部功能分解爲單獨的包,以便隔離複雜性。

新的源代碼結構(有可能會變化)

此外,代碼庫現在也用 TypeScript 編寫,相信 TypeScript 的類型系統和 IDE 的支持將讓新的代碼貢獻者更容易做出有意義的貢獻。

其他的改進

  • 改進編譯器
  • 支持 IE 11
  • 其他運行時改進
  • 改進觀察機制

 

二、Vue 3.0中的Composition-API嚐鮮

雖然 Vue 3.0 尚未發佈,但是其處於 RFC 階段的 Composition API 已經可以通過插件 @vue/composition-api 進行體驗了。

1、使用 Composition-API 風格重構邏輯

安裝 @vue/composition-api 插件以後,按照文檔在 main.js 引用便開啓了 Composition API 的能力。

  • main.js
import Vue from 'vue' import App from './App.vue' 
import VueCompositionApi from '@vue/composition-api' 

Vue.config.productionTip = false 
Vue.use(VueCompositionApi) 

new Vue({ 
    render: h => h(App), 
}).$mount('#app')

回到 App.vue,從 @vue/composition-api 插件引入 { reactive, computed, toRefs } 三個函數:

import { reactive, computed, toRefs } from '@vue/composition-api'

僅保留 components: { ... } 選項,刪除其他的,然後寫入 setup() 函數:

export default { 
    components: { ... }, 
    setup () {} 
}

接下來,我們將會在 setup() 函數裏面重寫之前的邏輯。

 

首先定義數據。

爲了讓數據具備“響應式”的能力,我們需要使用 reactive() 或者 ref() 函數來對其進行包裝,關於這兩個函數的差異,會在後續的章節裏面闡述,現在我們先使用 reactive() 來進行。

在 setup() 函數裏,我們定義一個響應式的 data 對象,類似於 2.x 風格下的 data() 配置項。

setup () {
    const data = reactive({
      todoList: [],
      showingStatus: 'all',
      onShowList: computed(() => {
        if (data.showingStatus === 'all') {
          return data.todoList
        } else if (data.showingStatus === 'completed') {
          return data.todoList.filter(({ completed }) => completed)
        } else if (data.showingStatus === 'uncompleted') {
          return data.todoList.filter(({ completed }) => !completed)
        }
      })
    })
}

其中計算屬性 onShowList 經過了 computed() 函數的包裝,使得它可以根據其依賴的數據的變化而變化。

 

接下來定義方法。

在 setup() 函數裏面,對之前的幾個操作選項的方法稍加修改即可直接使用:

    function submit (content) {
      data.todoList.push({
        completed: false,
        content,
        id: parseInt(Math.random(0, 1) * 100000)
      })
    }
    function onStatusChanged (status) {
      data.showingStatus = status
    }
    function toggleStatus ({ isChecked, id }) {
      data.todoList.forEach(item => {
        if (item.id === id) {
          item.completed = isChecked
        }
      })
    }
    function onItemDelete (id) {
      let index = 0
      data.todoList.forEach((item, i) => {
        if (item.id === id) {
          index = i
        }
      })
      data.todoList.splice(index, 1)
    }

與在 methods: {} 對象中定義的形式所不同的地方是,在 setup() 裏的方法不能通過 this 來訪問實例上的數據,而是通過直接讀取 data 來訪問。

 

最後,把剛剛定義好的數據和方法都返回出去即可:

    return {
      ...toRefs(data),
      submit,
      onStatusChanged,
      toggleStatus,
      onItemDelete,
    }

這裏使用了 toRefs() 給 data 對象包裝了一下,是爲了讓它的數據保持“響應式”的。

 

2、Composition API 的優勢及擴展

Vue 其中一個被人詬病得很嚴重的問題就是邏輯複用。隨着項目越發的複雜,可以抽象出來被複用的邏輯也越發的多。但是 Vue 在 2.x 階段只能通過 mixins 來解決(當然也可以非常繞地實現 HOC,這裏不再展開)。mixins 只是簡單地把代碼邏輯進行合併,如果需要對邏輯進行追蹤將會是一個非常痛苦的過程,因爲繁雜的業務邏輯裏面往往很難一眼看出哪些數據或方法是來自 mixins 的,哪些又是來自當前組件的。

另外一點則是對 TypsScript 的支持。爲了更好地進行類型推斷,雖然 2.x 也有使用 Class 風格的 ts 實現方案,但其冗長繁雜和依賴不穩定的 decorator 的寫法,並非一個好的解決方案。受到 React Hooks 的啓發,Vue Composition API 以函數組合的方式完成邏輯,天生就適合搭配 TypeScript 使用。

至於 Options API 和 Composition API 孰優孰劣的問題,在本文所展示的例子中其實是比較難區分的,原因是這個例子的邏輯實在是太過簡單。但是如果深入思考的話不難發現,如果項目足夠複雜,Composition API 能夠很好地把邏輯抽離出來,每個組件的 setup() 函數所返回的值都能夠方便地被追蹤(比如在 VSCode 裏按着 cmd 點擊變量名即可跳轉到其定義的地方)。這樣的能力在維護大型項目或者多人協作項目的時候會非常有用,通用的邏輯也可以更細粒度地共享出去。

關於 Composition API 的設計理念和優勢可以參考官網的 Motivation 章節

如果腦洞再開大一點,Composition API 可能還有更酷的玩法。

  • 對於一些第三方組件庫(如 element-ui),除了可以提供包含了樣式、結構和邏輯的組件之外,還可以把部分邏輯以 Composition API 的方式提供出來,其可定製化和玩法將會更加豐富。
  • reactive() 方法可以把一個對象變得響應式,搭配 watch() 方法可以很方便地處理 side effects:
const state = Vue.observable({ count: 0 })

const Demo = {
  render(h) {
    return h('button', {
      on: { click: () => { state.count++ }}
    }, `count is: ${state.count}`)
  }
}

上述例子中,當響應式的 state.count 被修改以後,會觸發 watch() 函數裏面的回調。基於此,也許我們可以利用這個特性去處理其他平臺的視圖更新問題。微信小程序開發框架 mpvue 就是通過魔改 Vue 的源碼來實現小程序視圖的數據綁定及更新的,如果擁有了 Composition API,也許我們就可以通過 reactive() 和 watch() 等方法來實現類似的功能,此時 Vue 將會是位於數據和視圖中間的一層,數據的綁定放在 reactive(),而視圖的更新則統一放在 watch() 當中進行。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章