How the interactive receiver UI components are compatible with Vue2 and Vue3
Interactive receiver SDK
Polyway Cloud live broadcast products can initiate interactions such as sign-in, lottery, and questionnaires during the live broadcast process. Correspondingly, these interactions also need to be presented on the viewing side. In order to make Polyway Cloud live viewing page and customer-customized viewing page can easily access these functions, we have made the interactive function into an SDK, that is, the interactive receiver SDK.
The interactive receiver SDK is developed in strict accordance with the separation of logic and UI . Based on the logic layer, you can develop UIs with different interfaces, and even UIs with different technology stacks. The default UI is developed based on Vue.js 2.6.
As we all know, Vue.js 3.x has been officially released. If a set of UI components developed based on Vue.js 2.6 is used in a Vue.js 3.x project, an error will occur; if a set of UI components that can be adapted to Vue.js 3.x is re-developed, it is necessary to maintain two A set of codes is not conducive to subsequent function iterative updates.
This article mainly describes how to build two versions of Vue.js components on the basis of one code, so as to adapt to Vue.js 2.6 and Vue.js 3.x (the following will refer to Vue.js 2.6 and Vue.js 3 respectively). .x is abbreviated as Vue2 and Vue3).
Introduction to Vue2 and Vue3 Compatible Architecture
On the basis of the original code, the packages of Vue2 and Vue3 are compiled and constructed respectively.
- Advantages: Subsequent functions are added or optimized, and the source code of interactive functions only needs to be changed once.
- Disadvantage: Unable to reference UI component libraries that are not compatible with Vue2 and Vue3. Cannot use Vue2, Vue3 incompatible syntax, including Vue3 new features.
Set up a Vue3 build environment for UI component projects
The original UI component project directory structure is as follows:
directory ui
directory vue2
- directory build
- directory src
- file package.json
- ..
In order to build a Vue3 build environment, create a new vue3 directory in the ui directory, and copy all configuration files except src in the vue2 directory. The directory structure is as follows:
directory ui
directory vue2
- directory build
- directory src
- file package.json
- ...
directory vue3
- directory build
- file package.json
- ...
Next, modify the configuration file in the vue3 directory, update vue
to 3.1 in package.json, install the same version of @vue/compat
and @vue/compiler-sfc
, and add vue- loader upgrade to above 16
"dependencies": {
- "vue": "^2.6.12",
+ "vue": "^3.1.0",
+ "@vue/compat": "^3.1.0",
- "vue-loader": "15.9.7"
+ "vue-loader": "16.0.0"
...
},
"devDependencies": {
+ "@vue/compiler-sfc": "^3.1.0"
}
After setting the alias @vue/compat
for vue
in Webpack's build configuration, incompatible code snippets in Vue3 can be detected.
Set the webpack entry file path to point to the source code in the src directory.
const srcDirname = path.resolve(__dirname, '../../vue2/src');
module.exports = {
entry: path.join(srcPath, 'main.js'),
resolve: {
alias: {
vue: '@vue/compat',
'@': srcDirname
}
},
...
}
The environment is now set up.
Handling code compatibility issues
After running the project, there are still problems opening the demo page, and abnormal information appears in the console. These problems need to be fixed before the project can run normally.
The problem is mainly caused by the following reasons: (For more compatibility issues, refer to the official documentation )
- Vue2 and Vue3 create nodes through extend and createApp respectively
- In Vue3
$options
property cannot be modified - Vue3 does not support filter filter
- Vue3 does not support slot syntax below 2.6
- Vue3 does not support global methods
$set
- Life cycle destroy and beforeDestroy, renamed unmounted and beforeUnmount in Vue3
Vue2 and Vue3 create nodes through extend and createApp respectively
For code that cannot be run in Vue2 and Vue3 at the same time, two sets of codes can be written separately by judging the version number
import Vue from 'vue';
function isVue3() {
return Vue.version.startsWith('3.');
}
if(isVue3()) {
// Vue3 环境代码
const TipApp = Vue.createApp(SubmitTip, propsData);
TipApp.mount(wrapContain);
// 业务代码...
} else {
// Vue2 环境代码
const Componet = Vue.extend(SubmitTip, propsData);
const TipApp = new Componet({
propsData
});
TipApp.$mount(wrapContain);
// 业务代码...
}
In Vue3 $options
property cannot be modified
Reason: In Vue2 $options
can be modified dynamically, but in Vue3 $options
properties are only readable and cannot be modified.
Solution: Move the logic code originally placed in $options
to data()
.
// 原来的写法
export default {
$i18n: null,
provide() {
// 初始化多语言实例
this.$options.$i18n = new I18n(this.$options.langs);
// 设置响应式语言属性
this.$options.$i18n.updateLocale(() => this.lang);
return {
getI18n: () => this.$options.$i18n
};
},
...
}
// 替代写法
export default {
data() {
return {
_i18n: null
}
}
provide() {
// 初始化多语言实例
this._i18n = new I18n(this.langs);
// 设置响应式语言属性
this._i18n.updateLocale(() => this.lang);
return {
getI18n: () => this._i18n,
};
},
...
}
Vue3 does not support filter filter
You can use methods instead of filter. E.g:
<!-- 过滤器filter写法 -->
<div> {{ date | dateFilter }}</div>
<!-- methods写法 -->
<div> {{ dateFilter(date) }}</div>
Vue3 does not support slot syntax below 2.6
Runs both Vue2 and Vue3 using the latest slot syntax. E.g:
<!-- 废弃语法-->
<template>
<template slot="header">
<h1> title </h1>
</template>
</template>
<!--2.6语法-->
<template>
<template v-slot:header>
<h1> title </h1>
</template>
</template>
Vue3 does not support global methods $set
Reason: Removed in Vue3 $set
.
Solution: Avoid using $set
, you can make sure that object properties have been handled reactively when defining or assigning objects and arrays in data()
.
<!--错误示例-->
<template>
<div v-for="(item,index) in list">
名字:{{ item.name }},
性别:{{ item.sex }},
</div>
</template>
<script>
export default {
data() {
return {
list: []
}
},
mounted() {
this.list.push({name: '张三'})
// 在vue3中不生效
this.$set(this.list[0], 'sex', 'man');
}
}
</script>
<!--正确示例-->
<template>
<div v-for="(item,index) in list">
名字:{{ item.name }},
性别:{{ item.sex }},
</div>
</template>
<script>
export default {
data() {
return {
list: []
}
},
mounted() {
this.list.push({name: '张三', sex: 'man'})
}
}
</script>
Life cycle destroy and beforeDestroy, renamed unmounted and beforeUnmount in Vue3
Use different method names by version judgment.
export const BEFORE_DESTROY = isVue3() ? 'beforeUmount' : 'beforeDestory';
export const DESTORY = isVue3() ? 'unmounted' : 'destory';
import { BEFORE_DESTROY } from '@/assets/utils/compat';
export default {
[BEFORE_DESTROY]() {
// 业务代码...
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。