Code前端首页关于Code前端联系我们

一、先想清楚,为啥非升级Vue3不可?

terry 3小时前 阅读数 4 #Vue
文章标签 Vue3 升级

最近不少前端同学纠结,公司老项目还在用Vue2,想升级到Vue3但怕踩坑,毕竟Vue3性能更强、生态更丰富,可从语法到工具链变化不少,到底咋平稳过渡?这篇把升级关键环节拆成问题挨个讲,从必要性到具体步骤、避坑技巧全涵盖,帮你少走弯路~

很多人觉得“项目能跑就别动”,但Vue3带来的好处真不是小打小闹。*性能肉眼可见提升**:响应式系统用Proxy替代Object.defineProperty,数组、对象新增属性这些场景不再犯难;编译阶段还有静态标记,重复渲染时能跳过静态节点,比如列表渲染多的页面,Vue3更新速度能快一半不止。

然后是生态和社区趋势,现在新出的UI库(像Naive UI、Vuetify 3)只支持Vue3,连Element UI都出了Plus版专为Vue3设计,要是项目想引入新组件库,Vue2根本接不上,而且Vue团队现在重心在Vue3,长期维护来看,Vue2的Bug修复、新特性支持会越来越少,早升级早享受后续红利。

还有代码可维护性,组合式API(Composition API)把逻辑按功能拆分,不像选项式API(data、methods一堆)容易出现“面条代码”,做复杂业务时,把请求、状态、逻辑封装成独立函数,复用和维护都轻松很多。

Vue2和Vue3核心语法差在哪?改代码前必须摸清这些!

升级第一步得懂“哪里不一样”,不然改代码准翻车,这几个核心差异是重灾区:

组件写法:选项式→组合式API的逻辑重组

Vue2里写组件是“按选项分类”:

export default {
  data() { return { count: 0 } },
  methods: { increment() { this.count++ } }
}

Vue3用组合式API后,逻辑集中到setup里,还得用ref/reactive让数据变响应式:

import { ref } from 'vue'
export default {
  setup() {
    const count = ref(0) // 基础类型用ref,对象/数组用reactive
    const increment = () => { count.value++ } // ref要通过.value改值
    return { count, increment } // 暴露给模板用
  }
}

要是嫌setup里return麻烦,还能直接用<script setup>语法糖(Vue3.2+支持),更简洁:

<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => count.value++
</script>

生命周期钩子变名了!

Vue2里的beforeDestroy→Vue3叫onBeforeUnmountdestroyedonUnmounted,其他钩子也有对应变化,比如beforeCreatecreated在组合式API里,逻辑直接写setup里(因为组件创建阶段setup已经执行)。

响应式原理升级,写代码得换思路

Vue2靠Object.defineProperty拦截属性,所以给对象新增属性(比如obj.newKey = 1)不触发更新,得用$set,Vue3用Proxy,能监听对象新增/删除属性,但reactive封装的对象,直接赋值会丢响应式

const state = reactive({ name: '张三' })
state = { name: '李四' } // 错误!直接替换会让Proxy失效
// 正确做法:用Object.assign改属性,或用ref包对象
const stateRef = ref({ name: '张三' })
stateRef.value = { name: '李四' } // 这样行

自定义指令钩子参数大变

Vue2写自定义指令是这几个钩子:bindinsertedupdate等,Vue3改成了createdbeforeMountmountedbeforeUpdate这些,和组件生命周期更统一,参数结构也变了,升级时得逐个检查指令逻辑。

事件总线没法直接用了

Vue2里常用this.$onthis.$emit搞全局事件,Vue3把实例上的$on$off全删了!要是还需要事件总线,得自己用mitt库实现,或者用Pinia的全局状态+action代替。

升级步骤咋规划?从环境到代码分阶段搞

盲目改代码准乱套,按步骤来更稳:

先搞定工具链:Node、CLI、构建工具

  • Node版本至少要14+(Vue3对Node版本有要求,老版本可能跑不起来)。
  • 要是用Vue CLI,先升级到最新版(npm update @vue/cli -g),但更推荐迁移到Vite——开发时热更新快到飞起,配置也比webpack简单,迁移Vite的话,得新建vite.config.js,把webpack的aliasproxy这些配置转过去,再处理依赖(比如把vue-loader换成@vitejs/plugin-vue)。

检查依赖库:哪些能留?哪些得换?

  • UI库:Element UI→Element Plus,Ant Design Vue 2→3,先看官网迁移指南,比如Element Plus组件名前缀从el-改成El-(大小写敏感),事件名也有调整(比如on-changeonUpdate:modelValue)。
  • 路由:vue-router 3→4,配置方式大变!Vue2是new VueRouter({ routes: [...] }),Vue3得用createRouter+createWebHistory
    import { createRouter, createWebHistory } from 'vue-router'
    const router = createRouter({
      history: createWebHistory(),
      routes: [...]
    })

    而且组件里拿路由要改用useRoute/useRouter(组合式API),不能再用this.$route

  • 状态管理:Vuex 3→4(兼容Vue3,但API没大改),或者直接换Pinia(Vue官方推荐,语法更简洁,支持组合式API),Pinia里没有mutations,直接用actions改状态,代码量少一半。

代码改造:从页面到组件,小步快跑

  • 先挑独立组件改(比如弹窗、表格),再改页面级组件,改的时候注意:
    • this没了:组合式API的setup里没有this,所以之前this.$storethis.$router得换成useStoreuseRouter(需导入对应函数)。
    • 插槽语法:Vue2的slot-scope→Vue3的v-slot,比如<template slot-scope="scope">改成<template v-slot="scope">
    • 过滤器(filter)被删了:Vue3不支持filter,得用计算属性或方法代替,比如{{ msg | uppercase }}改成{{ uppercase(msg) }},然后在methods里写uppercase函数。

测试+灰度:别直接全量上线

改完代码先跑单元测试(用Vue Test Utils升级到对应版本),确保逻辑没崩,然后搞灰度发布,比如先让部分用户(内部员工、测试环境)用新代码,收集反馈再全量推。

组件改造最容易踩的5个坑,避开能省半天班!

很多同学改代码时,明明语法对了,页面就是不更新、事件不触发,多半是踩了这些坑:

ref/reactive用错,响应式丢了

  • ref包基础类型(字符串、数字),但改值时忘写.valuecount++count.value++
  • reactive包对象,却直接赋值整个对象:state = { ... }→得用Object.assign(state, { ... })或者换ref包对象。
  • 解构reactive对象会丢响应式:const { name } = statename就不是响应式了,得用toRefs(state)把属性转成ref

自定义指令钩子逻辑失效

Vue2的bind对应Vue3的beforeMountinserted对应mounted,比如之前指令在inserted里操作DOM,Vue3得放到mounted里,不然DOM还没渲染完,获取节点会是空。

路由传参拿不到

Vue-router 4里,组件内拿参数不能用this.$route.params.id,得用useRoute()

import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id)

要是在选项式API里(没完全转组合式),还能暂时用this.$route,但Vue-router 4对选项式API支持是兼容的,长远还是得换组合式。

不渲染

Vue3的<slot>默认是作用域插槽,如果父组件没传内容,子组件得用<slot fallback="默认内容" />,不然插槽处会是空,具名插槽得用<template #name>,不能再用<slot name="name">这种写法。

第三方库兼容问题

比如老项目用了vue-lazyload(图片懒加载),Vue3版本得换@tanzhiyuan/vue3-lazyload(社区维护的适配版),升级前一定先查依赖的GitHub仓库,看有没有Vue3版本,没的话得找替代方案。

生态工具链咋适配?构建、路由、状态管理逐个击破

升级不只是改组件,工具链也得同步更新,不然开发体验和生产打包全出问题。

从Vue CLI到Vite:开发效率起飞

Vite基于ESModule,启动速度比Vue CLI快N倍,热更新也更丝滑,迁移时:

  • 新建vite.config.js,配置resolve.alias对应原来的webpack alias(比如指向src)。
  • 处理环境变量:Vue CLI的.env文件里的VUE_APP_XXX→Vite里要改成VITE_XXX,不然读不到。
  • 替换依赖:把vue-cli-plugin-xxx这类插件换成Vite插件(比如svg处理用vite-plugin-svg-icons)。

vue-router 4:配置和使用全变样

  • 路由模式:history: createWebHistory()(对应Vue2的mode: 'history'),createWebHashHistory对应哈希模式。
  • 动态路由:addRoute方法更灵活,但要注意重复添加的问题,需结合导航守卫处理。
  • 编程式导航:router.push({ name: 'xxx', params: { id: 1 } })和Vue2类似,但如果用组合式API,得先useRouter()拿到router实例。

Pinia替代Vuex:状态管理更简单

Pinia不需要写mutations,直接在actions里改state

import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
  state: () => ({ name: '' }),
  actions: {
    setName(newName) {
      this.name = newName // 直接改,不用commit mutation
    }
  }
})

组件里用的时候:

import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
userStore.setName('李四')

要是项目还想暂时用Vuex 4,得确保版本兼容(Vuex 4只支持Vue3,API和Vuex 3基本一致,但部分方法有调整)。

UI组件库:Element Plus这类咋迁移?

以Element Plus为例:

  • 安装:npm uninstall element-ui && npm install element-plus
  • 全局引入改按需引入(推荐):用unplugin-vue-components自动按需导入组件,不用手动写import { ElButton } from 'element-plus'
  • 样式引入:Element Plus的样式得单独导入import 'element-plus/dist/index.css',不像Element UI可以选主题。
  • 组件事件和属性:比如ElInputon-change事件→onUpdate:modelValuesize属性从smalldefault等,得对照官网迁移文档改。

大型项目升级有啥实战技巧?少走弯路的秘诀在这!

要是项目有几十上百个页面,全量改风险太大,这些技巧能救命:

渐进式升级:新旧代码共存

用webpack的alias,把部分Vue2组件指向Vue3版本,比如新建vue3-components目录,把要升级的组件放进去,然后配置:

// vue.config.js
module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        '@/components/old-component': '@/vue3-components/new-component'
      }
    }
  }
}

这样可以逐步替换组件,不用一次性改完。

用自动化工具批量改代码

社区有vue-codemod工具,能自动把Vue2的选项式API转成组合式API(比如把data里的变量转成refmethods转成setup里的函数),虽然不能100%准确,但能减少重复劳动,改完再人工检查。

单元测试+E2E测试全覆盖

升级前把所有关键流程的测试用例写好(用Jest+Vue Test Utils,或Cypress做E2E),改完代码跑一遍,能快速发现逻辑错误,比如表单提交、路由跳转这些核心功能,测试用例必须覆盖。

团队协作:文档和规范先行

升级前定好代码规范(比如统一用<script setup>语法糖,状态管理用Pinia),写一份《Vue3升级指南》给团队,把常见问题、迁移步骤写清楚,每天同步进度,遇到共性问题及时复盘,避免重复踩坑。

Vue2转Vue3不是一蹴而就,得从“为啥升”“哪里变”“咋操作”“咋避坑”这些维度逐个突破,只要把工具链、语法差异、生态适配这几块理清楚,再结合渐进式升级策略,老项目也能平稳过渡到Vue3,享受性能和开发体验的双重提升~要是你还有具体场景的疑问(比如某UI库咋迁移、某业务组件咋改),评论区随时聊~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门