隨著 Vue 3.0 進入到 Beta 階段,而且官方也給出了預計在七月中旬發佈 RC (Release Candidate), 以及正式版即將在八月發佈的明確目標,相信已經有不少朋友都想試試 Vue 3.0 了吧?

最近也 超前部署 花了一點時間將工作專案從 Vue 2.6 升級上 Vue 3.0 Beta, 這篇就簡單做個記錄,以及分享一些升級過程可能會遇到的坑。

環境說明

為了確保避免開發環境造成的差異,這裡先列出我目前使用的開發環境:

$ node -v
v14.3.0
$ yarn -v
1.22.4
$ npm -v
6.14.5
$ vue -V
@vue/cli 4.4.6

起手式

首先你得要有個 Vue 2.x (當初是以 VueCLI 建置) 的專案,然後在專案目錄下執行

$ vue add vue-next

這個時候, Vue CLI 會自動安裝對應的套件。

看到這個畫面就代表套件升級完成了,升級後可以檢查你的 package.json 檔案以及相關的版本是否有正確更新。

掛載點的變更

如果你是用 CLI 預設的 main.js 作為進入點,那麼 Vue CLI 會自動將原本的

import Vue from 'vue'

改為

import { createApp } from 'vue';

原本的掛載點

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

也會自動變成

createApp(App).use(router).use(store).mount('#app')

的新版語法。

如果你跟我一樣,使用的是多頁型的專案配置,那麼你會看到

Cannot find file src/main.js

找不到 main.js

的錯誤訊息。

不過沒關係,相關套件還是會升級,只是你得花點力氣人工手動將每一頁的進入點從 import vue from 'vue' 改成 import { createApp } from 'vue', 以及 new Vue({...}) 改成 createApp(App).mount('XXX') 的寫法。

el 屬性不再適用,而掛載時的 mount 也無需再加上 $ 了。

明顯的語法變動

多數的語法更新在執行 vue-cli-service lint 都會有提示。 這裡講一下更新時幾個明顯的語法變動。

首先是 filter option 被移除,替代方式很簡單就是搬到 methods 來使用,然後將 template 的 pipe 語法改寫。

事件修飾子的 .native 被移除,更準確的說是不需要了。

讓我花最多時間改寫的其實是 EventBus 的部分。

由於 Vue 3.0 移除了事件處理的 $on, $off 以及 $once, 使得過去我們透過一個空的 Vue 實體來當作事件訂閱/傳遞的載體 (俗稱 EventBus),這樣的方式已經不再適用, 對於這個問題,我的建議是:直上 Vuex。 你終究要用到 Vuex 的。

當然也有其他方法硬幹,就不在這篇的討論範圍

原本 2.x 的 options API 還是可以用,不用擔心 Vue 3.0 之後都得改成 setup 開頭了

取消 .sync 修飾子,新增多組 v-model

過去我們透過 prop.sync 來同步上下層 component 狀態 (俗稱雙向綁定) 的方式, 現在可以改由多組 v-model 來做到了:

<my-reg-form
  v-model:name="name"
  v-model:email="email" />
<!-- myRegForm.vue -->
<template>
  <input
    :value="name"
    @input="updateName($event.target.value)" />
  <input
    :value="email"
    @input="updateEmail($event.target.value)" />
</template>

<script>
export default {
  props: {
    name: String,
    email: String
  },
  setup (props, { emit }) {
    const updateName = value => {
      emit('update:name', value)
    }

    const updateEmail = value => {
      emit('update:email', value)
    }

    return { 
      updateName,
      updateEmail 
    }
  }
}
</script>

scoped styles 的改寫

CSS 的部分,原本我們為了將樣式穿透至子元素,會使用 /deep/>>> 的語法來處理,未來需要改成 ::v-deep() 的形式:

/* 即將廢棄 */
::v-deep .bar {}
/* Vue 3.0 的寫法 */
::v-deep(.bar) {}

並且新增了一個 ::v-global 的 pseudo element,可以用在 style scoped 的範圍下。

Vuex 的變動

既然講到 Vuex,那麼 Vuex 升級後有沒有什麼要注意的地方?

有的,將原本的

import Vuex from 'vuex'
export default new Vuex.Store({ ... })

改成

import { createStore } from 'vuex'
export default createStore({ ... })

就這樣,沒了。

其他

最後是 webpack 或 vue.config.jsalias 需要改成 vue$: 'vue/dist/vue.esm-bundler.js',否則 CLI 會告訴你他找不到 Vue,一直要你重裝。

目前升級 Vue 3.0 的開發體驗相當好,像是大家都很熟悉的 composition api、直接在 component 使用 v-model, 以及新增的 async-component 與 <Suspense> 等等,都是非常實用的功能。

缺點是截至目前還沒有 devtool 可以用,得憑經驗通靈。 聽說 RC 出來的時候就會有了 XD

工商服務

這篇只是記錄一下升級遇到的幾個問題。

如果你對 Vue 3.0 新增的部分也有興趣,剛好我在五倍紅寶石八月份有開設一門 Vue.js 與 Vuex 前端開發實戰課程教材已經更新至 3.0 (當然 2.x 也適用),歡迎你來參加。

參考資料與相關連結:

  1. https://github.com/vuejs/rfcs/issues/183/
  2. https://github.com/vuejs/vue-next
  3. https://github.com/vuejs/vue-cli-plugin-vue-next
  4. https://github.com/vuejs/rfcs/tree/master/active-rfcs