萝卜快跑不是一时的横空出世,其实在北京包括在武汉已经有几个年头,这次敢拉出来大规模应用,也是技术突破和不断尝试革新的实践,先不说损坏了多少人的利益,对于Ai而言是一次历史的里程碑,从这个角度是可歌的,😄言归正传,今日分享vue2升级到vue3一些步骤。
首先要了解,Vue 3 中需要关注的一些新特性包括:
- 组合式 API*
- 单文件组件中的组合式 API 语法糖 (<script setup>)*
- Teleport 组件
- Fragments 片段
- Emits 组件选项**
- 来自 @vue/runtime-core 的 createRenderer API 用来创建自定义渲染函数
- 单文件组件中的状态驱动的 CSS 变量 (<style> 中的 v-bind)*
- SFC <style scoped> 新增全局规则和针对插槽内容的规则
- Suspense 实验性
- 对 IE11 的支持:Vue 3 已经官方放弃对 IE11 的支持。如果仍然需要支持 IE11 或更低版本,那你仍需继续使用 Vue 2
准备工作
- 如果你仍然使用废弃的具名/作用域插槽语法,请先将其更新至 (2.6 已经支持的) 最新的语法。
安装
尽可能升级工具。
- 如果使用了自定义的 webpack 设置:将
vue-loader
升级至^16.0.0
。 - 如果使用了
vue-cli
:通过vue upgrade
升级到最新的@vue/cli-service
。 - (替代方案) 迁移至 Vite + vite-plugin-vue2。[示例提交]
- 如果使用了自定义的 webpack 设置:将
在
diffpackage.json
里,将vue
更新到 3.1,安装相同版本的@vue/compat
。且如果存在vue-template-compiler
的话,将其替换为@vue/compiler-sfc
。"dependencies": { - "vue": "^2.6.12", + "vue": "^3.1.0", + "@vue/compat": "^3.1.0" ... }, "devDependencies": { - "vue-template-compiler": "^2.6.12" + "@vue/compiler-sfc": "^3.1.0" }
在构建设置中,为
vue
设置别名@vue/compat
,且通过 Vue 编译器选项开启兼容模式。示例配置
vue-cli 普通 webpack Vite如果使用了 TypeScript,你还需要修改
tsvue
的类型,通过添加一个*.d.ts
暴露其 (在 Vue 3 中已经不再展示) 默认导出。declare module 'vue' { import { CompatVue } from '@vue/runtime-dom' const Vue: CompatVue export default Vue export * from '@vue/runtime-dom' const { configureCompat } = Vue export { configureCompat } }
在此,你的应用可能会遇到一些编译时的错误/警告 (例如对过滤器的使用),请先修复这些错误。直至所有的编译警告都消失,当然,你也可以把编译器设置为 Vue 3 模式。
在修复了这些错误之后,如果没有受制于上述的限制,那么应用就应该可以运行了。
你可能会同时从命令行和浏览器控制台看到很多警告。这里提供一些一般化的小建议:
你可以在浏览器控制台里过滤特定的警告。建议通过使用过滤器,使自己每次专注修复同一种问题。你也可以使用类似
-GLOBAL_MOUNT
的否定式过滤器。你可以通过兼容性配置关闭对特定的废弃内容的处理。
有些警告可能来自你使用的依赖 (如
vue-router
)。你可以通过警告的组件嵌套或调用栈的追踪信息 (可以点击展开) 来进行检查。可以优先专注于修复源自你自己代码的警告。如果你使用了
vue-router
,请注意在升级至vue-router
v4 之前,<transition>
和<keep-alive>
无法和<router-view>
一起工作。
升级 <transition> 类名。这是唯一没有运行时警告的特性。你可以在整个项目范围内做一次
.*-enter
和.*-leave
CSS 类名的搜索。更新应用的入口以使用新的全局挂载 API。
将 vue-router 升级至 v4。如果你还使用了
vuex-router-sync
,可以同时将其替换为一个 store getter。升级过后,同
<router-view>
一起使用<transition>
和<keep-alive>
就要求使用新的基于作用域插槽的语法。逐个修复警告。注意有些特性在 Vue 2 和 Vue 3 之间存在行为冲突——例如渲染函数 API,或函数式组件 vs. 异步组件的改变。为了迁移到 Vue 3 API 而不影响到应用的其它部分,你可以通过 compatConfig 选项对单个组件选择性启用 Vue 3 的行为。
当修复了所有警告以后,你就可以移除迁移构建版本并切换为 Vue 3。注意如果存在基于 Vue 2 行为的依赖,你可能无法做到这一点。
兼容性配置
全局配置
兼容性特性可以进行单独禁用:
js
import { configureCompat } from 'vue'
// 禁用某些兼容性特性
configureCompat({
FEATURE_ID_A: false,
FEATURE_ID_B: false
})
或者整个应用默认为 Vue 3 的行为,仅开启某些兼容性特性:
js
import { configureCompat } from 'vue'
// 所有 Vue 3 的默认行为,并开启某些兼容性特性
configureCompat({
MODE: 3,
FEATURE_ID_A: true,
FEATURE_ID_B: true
})
基于单个组件的配置
一个组件可以使用 compatConfig
选项,并支持与全局 configureCompat
方法相同的选项:
js
export default {
compatConfig: {
MODE: 3, // 只为这个组件选择性启用 Vue 3 行为
FEATURE_ID_A: true // 也可以在组件级别开启某些特性
}
// ...
}
针对编译器的配置
以 COMPILER_
开头的特性是针对编译器的:如果你正在使用完整构建版本 (含浏览器内编译器),它们可以在运行时中被配置。然而如果使用构建设置,它们必须换为通过在构建配置中的 compilerOptions
进行配置 (参阅上述的配置)。
非兼容性改变
全局API
模板指令
在 Vue 3.x 中,key
则应该被设置在 <template>
标签上。
html
<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>
vue3.x 版本中 v-if
总是优先于 v-for
生效。
后者属性覆盖前者
<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="blue"></div>
<!-- 模板 -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- 结果 -->
<div id="red"></div>
组件
- 函数式组件只能通过纯函数进行创建
- 单文件组件 (SFC) <template> 标签的 functional attribute 和函数式组件的 functional 选项已被移除
- 异步组件现在需要通过 defineAsyncComponent 方法进行创建
- 组件事件现在应该使用 emits 选项进行声明
渲染函数
- 渲染函数 API 更改
- $scopedSlots property 已移除,所有插槽都通过 $slots 作为函数暴露
- $listeners 被移除或整合到 $attrs
- $attrs 现在包含 class 和 style attribute
自定义元素
其他小改变
destroyed
生命周期选项被重命名为unmounted
beforeDestroy
生命周期选项被重命名为beforeUnmount
- Props 的 default 工厂函数不再可以访问 this 上下文
- 自定义指令的 API 已更改为与组件生命周期一致,且 binding.expression 已移除
- data 选项应始终被声明为一个函数
- 来自 mixin 的 data 选项现在为浅合并
- Attribute 强制策略已更改
- Transition 的一些 class 被重命名
- <TransitionGroup> 不再默认渲染包裹元素
- 当侦听一个数组时,只有当数组被替换时,回调才会触发,如果需要在变更时触发,则必须指定 deep 选项
- 没有特殊指令的标记 (
v-if/else-if/else
、v-for
或v-slot
) 的<template>
现在被视为普通元素,并将渲染为原生的<template>
元素,而不是渲染其内部内容。 - 已挂载的应用不会替换它所挂载的元素
- 生命周期的 hook: 事件前缀改为 vue:
被移除的 API
- keyCode 作为 v-on 修饰符的支持
- $on、$off 和 $once 实例方法
- 过滤器 (filter)
- 内联模板 attribute
- $children 实例 property
- propsData 选项
$destroy
实例方法。用户不应该再手动管理单个 Vue 组件的生命周期。- 全局函数
set
和delete
以及实例方法$set
和$delete
。基于代理的变化检测已经不再需要它们了。