Vue 2 项目迁移至 Vite + Vue 3 实战指南
项目背景
aiportal-ui 原本是 Vue 2 项目,现在运行在 Vite + Vue 3.5.34 环境,但可以使用 Vue 2 语法编写组件。
一、核心配置要点
1.1 vite.config.mjs - 启用 Options API
javascript
define: {
__VUE_OPTIONS_API__: true, // ← 关键:启用 Vue 2 Options API 风格
__VUE_PROD_DEVTOOLS__: false,
},
原理:Vue 3 默认关闭 Options API,通过这个全局变量启用它。
1.2 package.json - 依赖版本
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
javascript
import mitt from "mitt";
const emitter = mitt();
const bus = {
$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 风格):
javascript
// 组件中直接使用
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
javascript
import { h } from "vue";
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
// 将 Element Plus 的 API 适配成 Vue 2 风格
export const Message = (options) => ElMessage(options);
Message.success = (options) => ElMessage.success(...);
Message.warning = (options) => ElMessage.warning(...);
Message.error = (options) => ElMessage.error(...);
Message.info = (options) => ElMessage.info(...);
export const Modal = {
info(options = {}) { ... },
confirm(options = {}) { ... },
};
export const Notice = {
open(options) { return ElNotification(options); },
success(options) { ... },
// ...
};
// 安装函数
export function installUiCompat(app) {
app.config.globalProperties.$Message = Message;
app.config.globalProperties.$Modal = Modal;
app.config.globalProperties.$Notice = Notice;
app.component("Icon", IconCompat); // 自定义 Icon 组件
}
使用方式(Vue 2 风格):
javascript
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
javascript
import * as ViewUIPlus from "view-ui-plus";
function isIViewAliasName(name) {
return /^i[A-Z]/.test(name); // 检测 i 前缀
}
function removeIViewPrefix(name) {
return isIViewAliasName(name) ? name.slice(1) : name;
}
export function installViewUiPlusNs(app) {
Object.entries(ViewUIPlus).forEach(([, component]) => {
// 自动注册:去除 i 前缀(如 iButton -> Button)
const normalizedName = 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 风格):
html
<template>
<Button @click="handleClick">点击</Button>
<Breadcrumb>
<BreadcrumbItem>首页</BreadcrumbItem>
</Breadcrumb>
<Card>内容</Card>
</template>
三、main.js 完整初始化流程
javascript
import { createApp } from "vue";
import ElementPlus from "element-plus";
import zhCn from "element-plus/es/locale/lang/zh-cn";
import "element-plus/dist/index.css";
import "view-ui-plus/dist/styles/viewuiplus.css";
import mitt from "mitt";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import { installUiCompat } from "./plugins/ui-compat";
import { installViewUiPlusNs } from "./plugins/view-ui-plus-ns";
import i18n from "../i18n/index";
const app = 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 Router
app.use(router);
// 6. Vue I18n
app.use(i18n);
// 7. 全局混入会添加 handleError 方法
app.mixin({
methods: {
handleError(msg, err) { ... }
}
});
// 8. 事件总线
const emitter = mitt();
app.config.globalProperties.$bus = { $on, $off, $emit, on, off, emit };
// 9. 挂载
app.mount("#app");
四、关键差异对比
| 特性 | Vue 2 | Vue 3 兼容方式 |
|---|---|---|
| 事件总线 | Vue.prototype.$bus |
mitt + globalProperties |
$Message |
iView/Element UI | ui-compat.js 适配层 |
$Modal |
iView/Element UI | ui-compat.js 适配层 |
$Notice |
iView/Element UI | ui-compat.js 适配层 |
| 组件命名 | <i-Button> |
自动去除 i 前缀 <Button> |
| Vuex | Vuex |
vuex@4 + app.use(store) |
| 路由 | VueRouter@3 |
vue-router@4 |
五、迁移检查清单
如果要将一个 Vue 2 项目迁移到 Vite + Vue 3:
- package.json :升级
vue、vue-router、vuex到 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.js、src/plugins/view-ui-plus-ns.js - 入口文件 :
src/main.js - 构建配置 :
vite.config.mjs