VUE2_TO_VITE_VUE3

📅 2026/7/8 11:50:42 👁️ 阅读次数 📝 编程学习
VUE2_TO_VITE_VUE3

Vue 2 项目迁移至 Vite + Vue 3 实战指南

项目背景

aiportal-ui原本是 Vue 2 项目,现在运行在Vite + Vue 3.5.34环境,但可以使用Vue 2 语法编写组件。


一、核心配置要点

1.1 vite.config.mjs - 启用 Options API

define:{__VUE_OPTIONS_API__:true,// ← 关键:启用 Vue 2 Options API 风格__VUE_PROD_DEVTOOLS__:false,},

原理:Vue 3 默认关闭 Options API,通过这个全局变量启用它。

1.2 package.json - 依赖版本

{"vue":"^3.5.34","view-ui-plus":"^1.3.24",// ← Vue 3 版本的 iView"element-plus":"^2.11.1","vuex":"^4.1.0",// ← Vue 3 版本的 Vuex"vue-router":"^4.5.1","mitt":"^3.0.1"// ← 替代 Vue 2 的 $bus}

二、兼容性实现三大机制

2.1 机制一:mitt 替代 $bus(事件总线)

文件src/main.js

importmittfrom"mitt";constemitter=mitt();constbus={$on:emitter.on,$off:emitter.off,$emit:emitter.emit,on:emitter.on,off:emitter.off,emit:emitter.emit,};// 挂载到全局app.config.globalProperties.$bus=bus;

使用方式(Vue 2 风格)

// 组件中直接使用this.$bus.$on('eventName',this.handler)this.$bus.$emit('eventName',data)this.$bus.$off('eventName',this.handler)

2.2 机制二:ui-compat.js(UI 组件兼容层)

文件src/plugins/ui-compat.js

import{h}from"vue";import{ElMessage,ElMessageBox,ElNotification}from"element-plus";// 将 Element Plus 的 API 适配成 Vue 2 风格exportconstMessage=(options)=>ElMessage(options);Message.success=(options)=>ElMessage.success(...);Message.warning=(options)=>ElMessage.warning(...);Message.error=(options)=>ElMessage.error(...);Message.info=(options)=>ElMessage.info(...);exportconstModal={info(options={}){...},confirm(options={}){...},};exportconstNotice={open(options){returnElNotification(options);},success(options){...},// ...};// 安装函数exportfunctioninstallUiCompat(app){app.config.globalProperties.$Message=Message;app.config.globalProperties.$Modal=Modal;app.config.globalProperties.$Notice=Notice;app.component("Icon",IconCompat);// 自定义 Icon 组件}

使用方式(Vue 2 风格)

this.$Message.success('操作成功')this.$Modal.confirm({content:'确定删除?'})this.$Notice.warning({content:'警告'})

2.3 机制三:view-ui-plus-ns.js(iView 组件兼容)

文件src/plugins/view-ui-plus-ns.js

import*asViewUIPlusfrom"view-ui-plus";functionisIViewAliasName(name){return/^i[A-Z]/.test(name);// 检测 i 前缀}functionremoveIViewPrefix(name){returnisIViewAliasName(name)?name.slice(1):name;}exportfunctioninstallViewUiPlusNs(app){Object.entries(ViewUIPlus).forEach(([,component])=>{// 自动注册:去除 i 前缀(如 iButton -> Button)constnormalizedName=removeIViewPrefix(name);app.component(normalizedName,component);});// 全局方法app.config.globalProperties.$Message=ViewUIPlus.Message;app.config.globalProperties.$Notice=ViewUIPlus.Notice;app.config.globalProperties.$Modal=ViewUIPlus.Modal;}

使用方式(Vue 2 风格)

<template><Button@click="handleClick">点击</Button><Breadcrumb><BreadcrumbItem>首页</BreadcrumbItem></Breadcrumb><Card>内容</Card></template>

三、main.js 完整初始化流程

import{createApp}from"vue";importElementPlusfrom"element-plus";importzhCnfrom"element-plus/es/locale/lang/zh-cn";import"element-plus/dist/index.css";import"view-ui-plus/dist/styles/viewuiplus.css";importmittfrom"mitt";importAppfrom"./App.vue";importrouterfrom"./router";importstorefrom"./store";import{installUiCompat}from"./plugins/ui-compat";import{installViewUiPlusNs}from"./plugins/view-ui-plus-ns";importi18nfrom"../i18n/index";constapp=createApp(App);// 1. Element Plus(Vue 3 组件库)app.use(ElementPlus,{locale:zhCn});// 2. 自定义兼容层(Message/Modal/Notice/Icon)installUiCompat(app);// 3. View UI Plus(Vue 3 版本的 iView)installViewUiPlusNs(app);// 4. Vuex(Vue 3 版本)app.use(store);// 5. Vue Routerapp.use(router);// 6. Vue I18napp.use(i18n);// 7. 全局混入会添加 handleError 方法app.mixin({methods:{handleError(msg,err){...}}});// 8. 事件总线constemitter=mitt();app.config.globalProperties.$bus={$on,$off,$emit,on,off,emit};// 9. 挂载app.mount("#app");

四、关键差异对比

特性Vue 2Vue 3 兼容方式
事件总线Vue.prototype.$busmitt+globalProperties
$MessageiView/Element UIui-compat.js适配层
$ModaliView/Element UIui-compat.js适配层
$NoticeiView/Element UIui-compat.js适配层
组件命名<i-Button>自动去除 i 前缀<Button>
VuexVuexvuex@4+app.use(store)
路由VueRouter@3vue-router@4

五、迁移检查清单

如果要将一个 Vue 2 项目迁移到 Vite + Vue 3:

  • package.json:升级vuevue-routervuex到 v4 版本
  • vite.config.mjs:添加define: { __VUE_OPTIONS_API__: true }
  • main.js:改用createApp()而非new Vue()
  • 事件总线:引入mitt替代$bus
  • Message/Modal/Notice:创建兼容层适配新组件库
  • Icon 组件:检查并创建兼容实现
  • [第三方组件库:确保使用 Vue 3 版本(如view-ui-plus而非iview

六、文档路径

  • 示例项目D:\benchmarkui\portal\aiportal-ui
  • 兼容层src/plugins/ui-compat.jssrc/plugins/view-ui-plus-ns.js
  • 入口文件src/main.js
  • 构建配置vite.config.mjs

七、核心配置要点

1.1 vite.config.mjs - 完整的

import{defineConfig}from"vite";importvuefrom"@vitejs/plugin-vue";importpathfrom"path";import{fileURLToPath}from"url";import{viteStaticCopy}from"vite-plugin-static-copy";importbasicSslfrom"@vitejs/plugin-basic-ssl";const__filename=fileURLToPath(import.meta.url);const__dirname=path.dirname(__filename);exportdefaultdefineConfig({plugins:[basicSsl(),vue({template:{},}),viteStaticCopy({targets:[{src:path.resolve(__dirname,"static/**/*"),dest:"static",},],}),],// @element-plus/icons-vue 预构建时会直接从 vue 内部 chunk 拉 defineComponent,// 绕过了 vue 入口的 init_runtime_dom,导致 isFunction 未初始化即调用 defineComponent。optimizeDeps:{exclude:["@element-plus/icons-vue"],},resolve:{extensions:[".mjs",".js",".ts",".jsx",".tsx",".json",".vue"],alias:{"@common":path.resolve(__dirname,"../common"),"@":path.resolve(__dirname,"src"),"@U":path.resolve(__dirname,"src/utils"),"@P":path.resolve(__dirname,"static"),uuid:path.resolve(__dirname,"node_modules/uuid/dist/index.js"),},},define:{__VUE_OPTIONS_API__:true,__VUE_PROD_DEVTOOLS__:false,},server:{host:"ai.test.huawei.com",port:8080,https:true,proxy:{"/rest":{target:"https://platform-dev.ai.test.huawei.com/",ws:false,changeOrigin:true,secure:false,},},},build:{outDir:path.resolve(__dirname,"public","html"),emptyOutDir:true,},});

原理:Vue 3 默认关闭 Options API,通过这个全局变量启用它。

package.json调用

{"name":"data-management-ui","version":"0.1.0","private":true,"type":"module","scripts":{"serve":"vite --mode development","serve-uat":"vite --mode uat","build-prd":"node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode production","build-uat":"node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode uat","build-beta":"node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode beta","build-dev":"node --max_old_space_size=8192 node_modules/vite/bin/vite.js build --mode dev","lint":"eslint \"src/**/*.{js,vue}\" --fix","i18n:check":"node scripts/check-i18n-keys.mjs"},