跳至内容

迁移构建

概述

@vue/compat(又名“迁移构建”)是 Vue 3 的一个构建版本,它提供可配置的 Vue 2 兼容行为。

迁移构建默认情况下在 Vue 2 模式下运行 - 大多数公共 API 的行为与 Vue 2 完全相同,只有少数例外。使用在 Vue 3 中已更改或已弃用的功能将发出运行时警告。还可以根据组件启用/禁用功能的兼容性。

预期用例

  • 将 Vue 2 应用程序升级到 Vue 3(存在限制
  • 迁移库以支持 Vue 3
  • 对于尚未尝试过 Vue 3 的经验丰富的 Vue 2 开发人员,迁移构建可以用作 Vue 3 的替代方案,以帮助了解两个版本之间的差异。

已知限制

虽然我们已尽力使迁移构建尽可能地模仿 Vue 2 的行为,但仍存在一些限制,这些限制可能会阻止您的应用程序符合升级条件

  • 依赖于 Vue 2 内部 API 或未记录行为的依赖项。最常见的情况是使用 VNodes 上的私有属性。如果您的项目依赖于像VuetifyQuasarElementUI 这样的组件库,最好等待它们的 Vue 3 兼容版本。

  • Internet Explorer 11 支持:Vue 3 已正式放弃对 IE11 支持的计划。如果您仍然需要支持 IE11 或更低版本,则必须保留在 Vue 2 上。

  • 服务器端渲染:迁移构建可用于 SSR,但迁移自定义 SSR 设置要复杂得多。一般思路是用@vue/server-renderer 替换 vue-server-renderer。Vue 3 不再提供捆绑渲染器,建议使用Vite 与 Vue 3 SSR 结合使用。如果您使用的是Nuxt.js,最好等待 Nuxt 3。

期望

请注意,迁移构建旨在仅涵盖公开记录的 Vue 2 API 和行为。如果您的应用程序由于依赖于未记录的行为而无法在迁移构建下运行,我们不太可能调整迁移构建以满足您的特定情况。请考虑重构以消除对该行为的依赖。

提醒您:如果您的应用程序很大且很复杂,即使使用迁移构建,迁移也可能是一项挑战。如果您的应用程序不幸不适合升级,请注意,我们计划将 Composition API 和一些其他 Vue 3 功能移植到 2.7 版本(预计 2021 年第三季度末)。

如果您确实让您的应用程序在迁移构建上运行,您可以在迁移完成之前将其发布到生产环境。虽然存在少量性能/大小开销,但它不应明显影响生产 UX。当您有依赖于 Vue 2 行为且无法升级/替换的依赖项时,您可能需要这样做。

从 3.1 开始将提供迁移构建,并将继续与 3.2 发布系列一起发布。我们确实计划在未来的次要版本中最终停止发布迁移构建(不早于 2021 年年底),因此您仍然应该在此之前切换到标准构建。

升级工作流程

以下工作流程介绍了将实际的 Vue 2 应用程序(Vue HackerNews 2.0)迁移到 Vue 3 的步骤。完整的提交可以在此处找到。请注意,您的项目所需的实际步骤可能会有所不同,这些步骤应被视为一般指导,而不是严格的说明。

准备工作

安装

  1. 如果适用,升级工具。

    • 如果使用自定义 webpack 设置:将 vue-loader 升级到 ^16.0.0
    • 如果使用 vue-cli:使用 vue upgrade 升级到最新的 @vue/cli-service
    • (替代方案)迁移到Vite + vite-plugin-vue2。[示例提交]
  2. package.json 中,将 vue 更新到 3.1,安装相同版本的 @vue/compat,并用 @vue/compiler-sfc 替换 vue-template-compiler(如果存在)。

    diff
    "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"
    }

    示例提交

  3. 在构建设置中,将 vue 设为 @vue/compat 的别名,并通过 Vue 编译器选项启用兼容模式。

    示例配置

    vue-cli
    js
    // vue.config.js module.exports = {  chainWebpack: (config) => {  config.resolve.alias.set('vue', '@vue/compat')   config.module  .rule('vue')  .use('vue-loader')  .tap((options) => {  return {  ...options,  compilerOptions: {  compatConfig: {  MODE: 2  }  }  }  })  } }
    原生 webpack
    js
    // webpack.config.js module.exports = {  resolve: {  alias: {  vue: '@vue/compat'  }  },  module: {  rules: [  {  test: /\.vue$/,  loader: 'vue-loader',  options: {  compilerOptions: {  compatConfig: {  MODE: 2  }  }  }  }  ]  } }
    Vite
    js
    // vite.config.js export default {  resolve: {  alias: {  vue: '@vue/compat'  }  },  plugins: [  vue({  template: {  compilerOptions: {  compatConfig: {  MODE: 2  }  }  }  })  ] }
  4. 如果您使用的是 TypeScript,您还需要修改 vue 的类型以公开默认导出(在 Vue 3 中不再存在),方法是添加一个 *.d.ts 文件,其中包含以下内容

    ts
    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 }
    }

    请注意,此模块声明必须放置在一个 *.d.ts 文件中,该文件至少包含一个其他顶层导入或导出(export {} 就足够了),以便这些类型增强模块,而不是覆盖它。

  5. 此时,您的应用程序可能会遇到一些编译时错误/警告(例如,使用过滤器)。首先修复它们。如果所有编译器警告都消失了,您还可以将编译器设置为 Vue 3 模式。

    示例提交

  6. 修复错误后,如果应用程序不受上述限制的影响,则应用程序应该能够运行。

    您可能会从命令行和浏览器控制台看到很多警告。以下是一些一般性提示

    • 您可以在浏览器控制台中过滤特定警告。使用过滤器并专注于一次修复一个项目是个好主意。您也可以使用否定过滤器,例如 -GLOBAL_MOUNT

    • 您可以通过兼容性配置来抑制特定的弃用。

    • 某些警告可能是由您使用的依赖项引起的(例如,vue-router)。您可以从警告的组件跟踪或堆栈跟踪(单击展开)中检查这一点。首先专注于修复来自您自己源代码的警告。

    • 如果您使用的是 vue-router,请注意 <transition><keep-alive> 在您升级到 vue-router v4 之前将无法与 <router-view> 一起使用。

  7. 更新<transition> 类名。这是唯一没有运行时警告的功能。您可以对 .*-enter.*-leave CSS 类名进行项目范围的搜索。

    示例提交

  8. 更新应用程序入口以使用新的全局挂载 API

    示例提交

  9. vuex 升级到 v4.

    示例提交

  10. vue-router 升级到 v4。如果您还使用 vuex-router-sync,您可以用存储获取器替换它。

    升级后,要将<transition><keep-alive><router-view> 一起使用,需要使用新的基于作用域插槽的语法

    示例提交

  11. 逐个解决警告。请注意,某些功能在 Vue 2 和 Vue 3 之间存在冲突的行为 - 例如,渲染函数 API 或函数组件与异步组件的更改。为了迁移到 Vue 3 API 而不影响应用程序的其余部分,您可以使用compatConfig 选项在每个组件的基础上选择加入 Vue 3 行为。

    示例提交

  12. 当所有警告都修复后,您可以删除迁移构建并切换到 Vue 3 正式版。请注意,如果您仍然有依赖于 Vue 2 行为的依赖项,则可能无法执行此操作。

    示例提交

兼容性配置

全局配置

兼容性功能可以单独禁用

js
import { configureCompat } from 'vue'

// disable compat for certain features
configureCompat({
  FEATURE_ID_A: false,
  FEATURE_ID_B: false
})

或者,整个应用程序可以默认使用 Vue 3 行为,只启用某些兼容性功能

js
import { configureCompat } from 'vue'

// default everything to Vue 3 behavior, and only enable compat
// for certain features
configureCompat({
  MODE: 3,
  FEATURE_ID_A: true,
  FEATURE_ID_B: true
})

每个组件的配置

组件可以使用compatConfig 选项,该选项期望与全局configureCompat 方法相同的选项

js
export default {
  compatConfig: {
    MODE: 3, // opt-in to Vue 3 behavior for this component only
    FEATURE_ID_A: true // features can also be toggled at component level
  }
  // ...
}

编译器特定的配置

COMPILER_ 开头的功能是编译器特定的:如果您使用的是完整构建(带有浏览器内编译器),则可以在运行时配置它们。但是,如果使用构建设置,则必须通过构建配置中的compilerOptions 来配置它们(请参阅上面的示例配置)。

功能参考

兼容性类型

  • ✔ 完全兼容
  • ◐ 部分兼容,存在注意事项
  • ⨂ 不兼容(仅警告)
  • ⭘ 仅兼容(无警告)

不兼容

应该提前修复,否则可能会导致错误

ID类型描述文档
GLOBAL_MOUNT_CONTAINER已挂载的应用程序不会替换它挂载到的元素链接
CONFIG_DEVTOOLS生产环境的开发者工具现在是构建时标志链接
COMPILER_V_IF_V_FOR_PRECEDENCEv-ifv-for 在同一个元素上使用时的优先级已更改链接
COMPILER_V_IF_SAME_KEYv-if 分支不能再具有相同的键链接
COMPILER_V_FOR_TEMPLATE_KEY_PLACEMENT<template v-for> 键现在应该放在 <template>链接
COMPILER_SFC_FUNCTIONAL<template functional> 在 SFC 中不再受支持链接

部分兼容,存在注意事项

ID类型描述文档
CONFIG_IGNORED_ELEMENTSconfig.ignoredElements 现在是 config.compilerOptions.isCustomElement(仅在浏览器编译器构建中)。如果使用构建设置,则必须通过构建配置传递 isCustomElement链接
COMPILER_INLINE_TEMPLATEinline-template 已删除(仅在浏览器编译器构建中支持兼容性)链接
PROPS_DEFAULT_THISprops 默认工厂不再能访问 this(在兼容模式下,this 不是真正的实例 - 它只公开 props、$options 和注入)链接
INSTANCE_DESTROY$destroy 实例方法已删除(在兼容模式下,仅在根实例上受支持)
GLOBAL_PRIVATE_UTILVue.util 是私有的,不再可用
CONFIG_PRODUCTION_TIPconfig.productionTip 不再需要链接
CONFIG_SILENTconfig.silent 已删除

仅兼容(无警告)

ID类型描述文档
TRANSITION_CLASSES过渡进入/离开类已更改链接

完全兼容

ID类型描述文档
GLOBAL_MOUNTnew Vue() -> createApp链接
GLOBAL_EXTENDVue.extend 已删除(使用 defineComponentextends 选项)链接
GLOBAL_PROTOTYPEVue.prototype -> app.config.globalProperties链接
GLOBAL_SETVue.set 已删除(不再需要)
GLOBAL_DELETEVue.delete 已删除(不再需要)
GLOBAL_OBSERVABLEVue.observable 已删除(使用 reactive链接
CONFIG_KEY_CODESconfig.keyCodes 已删除链接
CONFIG_WHITESPACE在 Vue 3 中,空白默认值为 "condense"
INSTANCE_SETvm.$set 已删除(不再需要)
INSTANCE_DELETEvm.$delete 已删除(不再需要)
INSTANCE_EVENT_EMITTERvm.$onvm.$offvm.$once 已删除链接
INSTANCE_EVENT_HOOKS实例不再发出 hook:x 事件链接
INSTANCE_CHILDRENvm.$children 已删除链接
INSTANCE_LISTENERSvm.$listeners 已删除链接
INSTANCE_SCOPED_SLOTSvm.$scopedSlots 已删除;vm.$slots 现在公开函数链接
INSTANCE_ATTRS_CLASS_STYLE$attrs 现在包含 classstyle链接
OPTIONS_DATA_FNdata 在所有情况下都必须是函数链接
OPTIONS_DATA_MERGE来自 mixin 或扩展的 data 现在是浅层合并的链接
OPTIONS_BEFORE_DESTROYbeforeDestroy -> beforeUnmount
OPTIONS_DESTROYEDdestroyed -> unmounted
WATCH_ARRAY观察数组不再在变异时触发,除非是深度观察链接
V_ON_KEYCODE_MODIFIERv-on 不再支持 keyCode 修饰符链接
CUSTOM_DIR自定义指令钩子名称已更改链接
ATTR_FALSE_VALUE如果绑定值为布尔值 false,不再删除属性链接
ATTR_ENUMERATED_COERCION不再特殊情况枚举属性链接
TRANSITION_GROUP_ROOT<transition-group> 默认不再渲染根元素链接
COMPONENT_ASYNC异步组件 API 已更改(现在需要 defineAsyncComponent链接
COMPONENT_FUNCTIONAL函数组件 API 已更改(现在必须是纯函数)链接
COMPONENT_V_MODEL组件 v-model 已重新设计链接
RENDER_FUNCTION渲染函数 API 已更改链接
FILTERS过滤器已删除(此选项仅影响运行时过滤器 API)链接
COMPILER_IS_ON_ELEMENTis 的使用现在仅限于 <component>链接
COMPILER_V_BIND_SYNCv-bind.sync 被带有参数的 v-model 替换链接
COMPILER_V_BIND_PROPv-bind.prop 修饰符已删除
COMPILER_V_BIND_OBJECT_ORDERv-bind="object" 现在对顺序敏感链接
COMPILER_V_ON_NATIVEv-on.native 修饰符已删除链接
COMPILER_V_FOR_REFv-for 中的 ref(编译器支持)
COMPILER_NATIVE_TEMPLATE没有特殊指令的 <template> 现在将渲染为原生元素
COMPILER_FILTERS过滤器(编译器支持)