前言
理論上 Vue3.x大多數的寫法是有向下相容 Vue2.x的寫法,所以理論上.vue
檔Component的寫法只要同時符合 Vue3.x和 Vue2.x的寫法,是能夠將同一個檔案共用於兩者不同環境當中。
以下會針對幾種我遇過在這兩個環境中較大差異的部份以及解決方式做個說明。
v-model
Vue2.x和 Vue3.x Component雙向綁定主要有兩個差異:
- Vue3.x移除了
.sync
寫法,並且單一 Component中可有多個v-model
。 v-model
對應的prop
和event
預設名稱不同。
在 Vue2.x的環境當中,v-model
預設對應 v-bind:value
和 @input
,例如:
<input :value="syncValue" @input="handleInput"/>
<!-- 等同於 -->
<input v-model="syncValue"/>
在 Vue3.x的環境當中,v-model
預設對應 v-bind:modelValue
和 @update:modelValue
<input :modelValue="syncValue" @update:modelValue="handleInput"/>
<!-- 等同於 -->
<input v-model="syncValue"/>
綜合以上即可得出一個結論,只要使用 model
欄位設定預設的prop
和event
為和 Vue3.x預設值相同,那麼就可以讓這個 Component的v-model
同時相容於 Vue2.x和 Vue3.x。
也就是只要在 option當中加入這個即可:
model: {
prop: 'modelValue',
event: 'update:modelValue'
}
範例如下:
<template>
<input v-model="syncValue"/>
</template>
<script>
export default {
// 使用 model設定預設的 prop及 event名稱
model: {
prop: 'modelValue',
event: 'update:modelValue'
},
props: ['modelValue'],
computed: {
syncValue: {
get () {
return this.modelValue
},
set (v) {
this.$emit('update:modelValue', v)
}
}
}
</script>
偵測環境
在某一些更複雜的情況,已經沒有辦法在同一支程式入同時相容於 Vue2.x和 Vue3.x兩個環境,必需要分成兩支程式才行,這時候我們可能就會需要用程式來判斷目前的環境是 Vue2.x還是 Vue3.x,再「動態import」進來所對應的程式(需注意,如果是採用一般的 import方式可能會在 webpack打包時就依賴所有程式造成出錯)。
Vue實例在這兩者環境底下會有不同東西,我自己採用的判斷依據是判斷 Vue實例底下是否有_isVue
,如果有的話就是 Vue2.x、沒有的話就是 Vue3.x,例:
if (this._isVue) {
// vue2.x
} else {
// vue3.x
}
完整範例:
<template>
<component
:is="dynamicComponent">
</component>
</template>
<script>
export default {
data () {
return {
dynamicComponent: undefined
}
},
created () {
if (this._isVue) {
// dynamic component (vue2.x)
this.dynamicComponent = () => import('./ComponentV2.vue')
return
}
// dynamic component (vue3.x)
import('./ComponentV3.vue')
.then(d => this.dynamicComponent = d.default)
}
}
</script>
Functional Component
Function Component在 Vue2.x和 Vue3.x當中有非常大幅度的 breaking change,所以基本上如果要相容的話肯定是要分別寫成不同的程式的。
就我的經驗當中這個部份是最花時間,而且挫折感最重的地方,建議先將官網文件完整看過一遍,再開始從簡單的 Component實作中練習起:
https://v3.vuejs.org/guide/migration/functional-components.html#overview
結論
應該還會有很多我沒有實作過的不同情況,以上就以我自己的經驗所遇過的情況跟大家分享囉。