前言
选择vue2,是因为我们的网页需要支持IE11。
但是同时,我们又非常向往vue3那种组合式API的开发方式。
我们还希望有vite,用于加快服务器启动和打包的速度。
为了进一步写出规范的代码,减少出错的可能,我们再用上TypeScript,TypeScript的使用,除了更好的类型判断,最最重要的,是更好的面向接口编程。
Vue2和Vue3怎么选择?
对于vue2和vue3的选择,主要需要考虑的点还是在vue3的兼容性上。
vue3兼容性的限制取决于浏览器对Proxy对象的支持。而且这个不兼容无法通过babel抹除。
babel不支持proxy:
Unsupported feature
Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled. See support in various JavaScript engines.
proxy的兼容性:
可以看到,不兼容的浏览器大概占比有3.5%左右。
由此我们的策略是:
- 可用性要求高的外部的web,用vue2。
- 其他的,比如工具类、内部的web,大胆用vue3。
vue2使用组合式api的体验如何?
我们的工程一开始就是用vue3写的,技术栈是vue3+vite+ts,用上了组合式api和<script setup>
语法糖等新特性。
后面因为兼容性问题改成vue2.6.x,这个修改的过程,需要改的地方,非常少。
7月份vue2.7.x也发布release版本,和vue3更加相似,需要改的地方就更少了。
下文实践环节,主要介绍vue2.7的开发流程。
如果对vue2.7+组合式api的开发流程感兴趣,可以参考另一篇文章Vue2+TypeScript+CompositionAPI实践。
将会学到什么?
使用如下的技术栈搭建web工程
- vue2.7
- vite
- TypeScript
- 组合式API+
<script setup>
语法糖
开始实践
vue2.7的特性
下面先看看vue2.7向后兼容的特性:
- 把
@vue/composition-api
合并进 Vue 2。这会让使用 Composition API 开发的库同时支持 Vue2 和 Vue3。- 单文件组件中的
<script setup>
语法。- 提升的 TypeScript 类型支持。
- 正式在 Vite 中支持 Vue 2,新增官方的@vitejs/plugin-vue2插件(2.6的支持是通过非官方插件 vite-plugin-vue实现的)
创建vue2.7 的ts项目
vite没支持直接创建vue2项目,我们直接用vite创建一个vue3+ts的项目就可以,然后再修改vue的版本为2.7.x。
可以看到.vue文件已经是用上和组合式api
和<script setup>
语法糖,我们不需要再做修改。
需要注意vue对象中没有createApp
,如果要用,还是得引入@vue/composition-api
。
(2.6版本:需要引入@vue/composition-api
,修改ref
从@vue/composition-api
引入)
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
vite支持vue2
vite支持vue2需要用到@vitejs/plugin-vue2插件。
//vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue2';
export default defineConfig({
plugins: [
vue(),
],
}
ESLint和TypeScript配置
eslint-plugin-vue
需要升级到9.x版本,同时ts配置文件加上下面的代码,否则<template>
标签中的变量会报未定义的错误。
//tsconfig.json
"vueCompilerOptions": {
"target": 2.7
}
vue2.7的限制
以下功能已明确不会进行移植:
createApp()
(Vue 2 没有独立的 app scope)- Top-level
await
in<script setup>
(Vue 2 不支持异步组件初始化)- 在模板表达式中支持 TypeScript 语法(不兼容 w/ Vue 2 解析器)
- 响应式转换 Reactivity transform(仍处于实验性阶段)
expose
选项不支持 options 组件(但<script setup>
支持defineExpose()
)
兼容更多的浏览器版本
npm run build
查看构建产生的文件,我们可以发现其js文件是作为module模块引入的,这是因为vite默认支持的浏览器基线是支持ESM的现代浏览器。
所以像IE 11这种传统浏览器是不支持的。
兼容传统浏览器
测试兼容性可以用下面这个在线工具:测试浏览器兼容性的在线工具](app.lambdatest.com/console/rea…)
为了兼容IE11,我们需要用到@vitejs/plugin-legacy
这个插件,我们先按官网的方式引入。
// vite.config.ts
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults']
})
]
}
兼容停止维护的浏览器
target值的知识,参考browserslist
。
发现在IE 11依旧白屏,我们看看defaults
的值是什么:> 0.5%, last 2 versions, Firefox ESR, not dead
IE 11已经停止维护,已经被排除在not dead
之外。
稍微修改一下target的值targets: ['> 0.01%, last 10 versions, Firefox ESR']
。
可以了!