同事以为要重写,我8行代码让 Vue 2 公共组件跑进 Vue 3

前言

最近遇到一个非常典型的前端兼容问题:产品要求将官网底部 footer 组件统一成公司平台的公共组件。查阅对接文档后发现,这个公共组件库是基于 Vue 2 开发的,而我们的项目已经升级到 Vue 3

这就尴尬了,难道要为了一个组件降级整个项目?或者重新写一遍?都不现实。

最后我想到一个解决方案:在 Vue 3 项目中动态加载并运行 Vue 2 组件。经过实践,成功解决了这个问题,今天分享给大家。

环境准备:先安装 Vue 2 依赖

由于我们需要在 Vue 3 项目中动态加载 Vue 2 的运行时和vue2组件,必须先安装 Vue 2 相关依赖。否则 import 时会报模块未找到的错误。

安装命令

perl 复制代码
# 安装 Vue 2 运行时
npm install vue@2

# 安装 Vue 2 公司公共组件
npm install @xxx/navigation-components

解决思路

基本思路是这样的:

  1. 动态加载 Vue 2 的运行时代码和目标组件;

  2. 在 Vue 3 组件中创建独立的 Vue 2 实例,与主项目隔离;

  3. 将 Vue 2 组件挂载到指定 DOM 节点

  4. 通过 props 传递数据,甚至事件通信。

    Vue 3 项目
    ├── 正常的 Vue 3 组件
    ├── 动态导入 Vue 2 运行时
    ├── 创建独立的 Vue 2 实例
    └── Vue 2 组件在独立实例中运行

这种方式可以让 Vue 2 组件像"小程序"一样在 Vue 3 项目中运行,互不干扰。


具体实现

1. 动态导入资源

动态加载资源,这样打包的时候就会进行代码分割,减少主包体积,提升首屏性能。

js 复制代码
import Vue2 from 'vue2/dist/vue.runtime.min.js'  // vue2运行时
import * as vue2Component from 'xxx/navigation-components' // vue2公共组件

打包结果:

css 复制代码
dist/
├── index.html
├── main.js (500KB)           ← 主要代码
├── vue2.chunk.js (34KB)      ← Vue 2 运行时
├── nav.chunk.js (15KB)       ← 导航组件
└── main.css

在组件中按需引入之后,打包的时候把不是立即需要的代码(如Vue2运行时、第三方组件)单独打包,等到需要使用到的时候才下载,这样主包变小,首屏加载更快,用户体验更好。如果不是按需加载,在main.js中直接引入的话,用户访问网站就必须等主包下载完才能看到页面。

优势:

  • 并行加载,提升加载速度
  • 代码分割,减少主包体积
  • 按需加载,优化首屏性能

在vue3文件中创建 Vue 2 实例

js 复制代码
<script setup>
import { onMounted } from 'vue';
import Vue2 from 'vue2/dist/vue.runtime.min.js'
import vue2Component from 'xxx/navigation-components'

onMounted(async () => {
   new Vue2({
      el: '#nav-footer',
      render: (h) => h(vue2Component)}
   )
})
</script>

模板中预留挂载点

vue3 复制代码
<template>
  <div>
    <!-- Vue 3 的其他内容 -->
    <main>...</main>
    
    <!-- 为 Vue 2 组件预留挂载点 -->
    <div id="nav-footer"></div>
  </div>
</template>

优势总结

  1. 兼容性好:无需修改现有 Vue 3 项目架构

  2. 隔离性强:Vue 2 和 Vue 3 实例完全独立,互不影响

  3. 性能优化:按需加载,代码分割

  4. 维护成本低:可以直接使用现有的 Vue 2 组件

源码

js 复制代码
<script setup>
import { onMounted } from 'vue';
import Vue2 from 'vue2/dist/vue.runtime.min.js'
import vue2Component from 'xxx/navigation-components'

onMounted(async () => {
   new Vue2({
      el: '#nav-footer',
      render: (h) => h(vue2Component)}
   )
})

</script>
<template>
  <div id="nav-footer"></div>
</template>

总结

用这个方案,Vue 3 项目也能直接用 Vue 2 组件,不用大改项目,也不用重写代码。这样既兼容又省事,还能让页面加载更快,维护也更简单。适合项目升级过渡时用,等以后有时间,再慢慢把组件升级到 Vue 3 就行了。

如果这篇文章对你有帮助,记得点赞👍收藏⭐分享📤三连哦~

相关推荐
不听话坏4 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
likeyi074 小时前
require 和 import的区别
开发语言·前端
pany4 小时前
做 AI 友好的开源 Vue3 模板 🌈
前端·vue.js·ai编程
小二·5 小时前
React 19 + Next.js 15 现代前端开发实战:App Router / Server Components / 流式渲染
前端·javascript·react.js
daols886 小时前
vue 甘特图 vxe-gantt 小时视图设置日期轴每间隔 3 个小时
vue.js·甘特图·vxe-gantt
谙忆10246 小时前
前端图片直传对象存储:OSS/S3 预签名 URL、STS 临时凭证与回调校验
前端
CHNE_TAO_EMSM7 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
一孤程8 小时前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒8 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai9 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript