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

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 :升级 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
相关推荐
苏瞳儿9 小时前
vue3+pinia+mqtt实时响应连接
前端·javascript·vue.js
i220818 Faiz Ul10 小时前
理财系统|基于java+vue的家庭理财系统小程序(源码+数据库+文档)
java·vue.js·spring boot·小程序·论文·毕设·理财系统
暗冰ཏོ10 小时前
《2026 Vue2 + Vue3 完整学习指南:基础语法、路由缓存、登录拦截、项目实战与面试题》
前端·vue.js·vue·vue3·vue2
蜡台10 小时前
VUE 侧边按钮组,可自定义位置
前端·javascript·css
AI科技星10 小时前
维度原本——基于超复数谱系的全域维度统一理论
c语言·前端·javascript·网络·electron
遇事不決洛必達10 小时前
【爬虫随笔】常见加密算法特征总结
javascript·爬虫·逆向·加密算法
kyriewen10 小时前
14MB VS 15KB:前React核心成员用AI写了个排版库,让Safari快了一千倍
前端·javascript·react.js
幸运小圣11 小时前
动态表格在 Vue 3 中的实现指南【前端】
前端·javascript·vue.js
SwJieJie11 小时前
Day 3|表格表单分页范式与 vue-request 最佳实践:从配置驱动到业务落地
前端·javascript·vue.js