本文提出基于ClaudeCode的渐进式重构策略,将Vue2项目分六个阶段迁移至Vue3,包括基础设施准备、核心API替换、ElementUI转ElementPlus等关键步骤,利用AI提升迁移效率与代码一致性,并同时提供详细提示词与变化速查表,助力开发者快速、平滑完成升级。
Claude Code将Vue2老项目重构为Vue3指南
时间:2026-08-14
浏览:251
文章目录
一、重构整体策略
1.1 核心原则:渐进式重构,而非推倒重来
老项目重构,最怕的不是技术有多难,而是——业务中断。你费了半天劲,结果线上出问题了,那是真·翻车。所以,这里推荐一个稳妥的打法:渐进式分阶段重构,一点点来,别想着一步到位。下面这个表格把整个流程拆成了六个阶段,从风险最低的基础设施准备,到最后的全面拥抱 Vue3,每一步都有明确目标和并行策略。

| 阶段 | 目标 | 风险等级 | 是否可并行开发 |
|---|---|---|---|
| Phase 0 | 基础设施准备(构建工具、依赖升级) | 是 | |
| Phase 1 | Vue2 → Vue3(兼容模式) | 是 | |
| Phase 2 | ElementUI → Element Plus | 否(UI 层需统一) | |
| Phase 3 | Vuex → Pinia | 是(可共存) | |
| Phase 4 | Ja vaScript → TypeScript | 是(逐文件迁移) | |
| Phase 5 | 清理兼容层,全面拥抱 Vue3 | 否 |
1.2 为什么用 Claude Code 而不是手动重构
手动重构不是不行,但代价你得算:
- 速度快:像批量替换 API、组件属性映射这种机械活儿,AI 比人快 10 倍以上,而且不喊累。
- 一致性高:同一类改动,AI 不会出现漏改或风格不统一的问题——人反而容易手滑。
- 边改边学:AI 会解释每处改动的原因,团队成员可以一边重构一边熟悉 Vue3 的新写法,等于免费培训。
- 可回退:按文件或按模块提交,出问题可以精准回滚,不用整锅端。
二、Phase 0:基础设施准备
2.1 重构前的准备工作
让 AI 动手之前,这几件事先搞定:
- 创建独立分支:
git checkout -b refactor/vue3-migration - 锁定当前版本:确保
package-lock.json或yarn.lock已提交,别让依赖版本乱跑。 - 跑通测试:重构前确保所有测试通过,作为基准,后面改完一对比就知道有没有坏。
- 梳理项目结构:让 AI 先了解项目全貌,别让它盲人摸象。
2.2 构建工具升级建议
构建工具这块,根据你的现状选方案:
| 当前工具 | 推荐升级为 | 原因 |
|---|---|---|
| Vue CLI | Vite | 开发体验提升巨大,Vue3 官方推荐 |
| Webpack 4 | Webpack 5 + vue-loader@16 | 渐进式升级,改动较小 |
| Babel + ESLint | @vitejs/plugin-vue + eslint-plugin-vue | 配合 Vite 使用 |
三、Phase 1:Vue2 → Vue3 核心迁移
3.1 迁移思路
Vue3 提供了一个 @vue/compat 兼容模式,可以让 Vue2 代码在 Vue3 环境下先跑起来,然后逐步移除兼容模式。这就像给旧房子加个过渡支架,拆一块换一块,不用一次性推倒。
推荐路径:
- 先升级到 Vue 2.7(Vue2 的最后一个版本,内置 Composition API)
- 新组件直接用
+ Composition API 写 - 老组件逐步改造
- 全部改完后切换到 Vue3 正式模式
3.2 核心 API 变化速查表
下面这张表把 Vue2 和 Vue3 的 API 对应关系整理出来了,建议存一份,迁移时随时查:
| Vue2 | Vue3 | 说明 |
|---|---|---|
new Vue() | createApp() | 应用实例创建方式 |
Vue.use() | app.use() | 插件注册 |
Vue.component() | app.component() | 全局组件注册 |
Vue.prototype.$xxx | app.config.globalProperties.$xxx | 全局属性 |
this.$emit | defineEmits() | 事件定义 |
props: { ... } | defineProps<{ ... }>() | Props 定义(TS 方式) |
data() { return {} } | ref() / reactive() | 响应式数据 |
computed: {} | computed(() => {}) | 计算属性 |
watch: {} | watch() / watchEffect() | 侦听 |
methods: {} | 普通函数 | 方法直接定义 |
filters | 移除,用方法或计算属性替代 | 过滤器已废弃 |
$listeners | 移除,合并到 $attrs | 监听器 |
.native 修饰符 | 移除 | 原生事件修饰符 |
v-model (prop: value, event: input) | v-model (prop: modelValue, event: update:modelValue) | v-model 变化 |
.sync | v-model:propName | 替换 .sync |
slot-scope | v-slot | 插槽语法 |
keep-alive + router-view | | 路由缓存写法 |
transition 类名 | v-enter-from 替代 v-enter | 过渡类名 |
destroyed / beforeDestroy | unmounted / beforeUnmount | 生命周期 |
Vue.set / Vue.delete | 直接赋值 / 删除 | Proxy 袋里无需 set |
3.3 Claude Code 提示词:Vue2 组件转 Vue3
下面这几个提示词,直接复制到 Claude Code 里就能用,节省你写 prompt 的时间。注意替换代码块里的占位符。
提示词 1:单文件组件整体迁移(Options API → Composition API)
你是一个 Vue3 迁移专家。请将以下 Vue2 单文件组件(SFC)重构为 Vue3 的
提示词 2:批量迁移一个目录下的所有组件
你是一个 Vue3 迁移专家。我需要你帮我批量重构 src/components/ 目录下的所有 Vue2 组件为 Vue3
提示词 3:main.js / main.ts 入口文件迁移
请将以下 Vue2 的 main.js 入口文件重构为 Vue3 的 main.ts 写法,要求:
1. new Vue() 改为 createApp()
2. Vue.use() 改为 app.use()
3. Vue.component() 改为 app.component()
4. Vue.prototype 改为 app.config.globalProperties
5. 引入方式从 'vue' 改为正确的 Vue3 引入
6. 如果有 Vuex,先保持 Vuex 的写法(后续单独迁移)
7. 如果有 ElementUI,先保持(后续单独迁移)
8. 加上必要的 TypeScript 类型
9. 保持所有插件和配置的顺序不变
原始代码:
---
{粘贴你的 main.js 代码}
---
四、Phase 2:ElementUI → Element Plus
4.1 迁移思路
ElementUI 和 Element Plus 的 API 有差异,但整体组件命名风格接近。建议分三步走:
- 先全局替换前缀:
el-前缀不变,但组件名的大小写规范要统一(Element Plus 对大小写更敏感)。 - 逐个组件检查:重点关注那些 API 变化较大的组件,比如表格、表单、上传。
- 样式变量替换:SCSS 变量名变化较大,注意 CSS 变量前缀从
--color-变成了--el-color-。
4.2 主要变化速查表
| ElementUI (Vue2) | Element Plus (Vue3) | 说明 |
|---|---|---|
Vue.use(ElementUI) | app.use(ElementPlus) | 全局注册 |
this.$message | ElMessage | 消息提示(需手动导入) |
this.$confirm | ElMessageBox.confirm | 确认框 |
this.$alert | ElMessageBox.alert | 警告框 |
this.$prompt | ElMessageBox.prompt | 输入框 |
this.$notify | ElNotification | 通知 |
this.$loading | ElLoading | 加载 |
size="medium" | size="default" | 尺寸变化 |
type="info" | type="info"(多数不变) | 类型基本不变 |
el-table 的 prop | 不变 | 表格列属性 |
el-dialog 的 visible.sync | v-model="visible" | 对话框 |
el-drawer 的 visible.sync | v-model="visible" | 抽屉 |
el-select 的 value / label | value / label(基本不变) | 选择器 |
el-form 的 label-position | 不变 | 表单 |
el-pagination 的 current-page.sync | v-model:current-page | 分页 |
el-tabs 的 value | v-model | 标签页 |
el-menu 的 default-active | default-active(不变) | 菜单 |
el-tree 的 node-key | 不变 | 树形控件 |
el-upload 的 file-list | file-list(基本不变) | 上传 |
主题色 --color-primary | --el-color-primary | CSS 变量前缀变化 |
$--color-primary | @use 'element-plus/theme-chalk/src/index' | SCSS 变量引入方式变化 |
el-icon-xxx | 或 | 图标使用方式大变 |
4.3 高风险组件(需要重点检查)
以下组件的 API 变化较大,建议人工 review 一遍,别全信 AI 的自动替换:
- el-table:部分事件参数变化、排序/筛选 API 调整
- el-form:校验规则的类型定义变化大
- el-upload:文件列表结构、上传钩子参数变化
- el-tree:节点数据结构、节点操作方法变化
- el-date-picker:值格式、快捷选项 API 变化
- el-select:远程搜索、虚拟滚动 API 变化
4.4 Claude Code 提示词:ElementUI 转 Element Plus
提示词 1:单组件 ElementUI → Element Plus 迁移
你是一个 Element Plus 迁移专家。请将以下 Vue 组件中的 ElementUI 用法全部替换为 Element Plus 的写法,要求:
1. 组件名保持 el- 前缀不变(Element Plus 也用 el- 前缀)
2. 重点检查并替换以下内容:
- this.$message → ElMessage(需 import { ElMessage } from 'element-plus')
- this.$confirm → ElMessageBox.confirm
- this.$alert → ElMessageBox.alert
- this.$notify → ElNotification
- this.$loading → ElLoading.service
- visible.sync → v-model(dialog、drawer 等)
- value.sync → v-model:value(或对应 prop 名)
- el-icon-xxx 类名方式 → 组件方式
- size="medium" → size="default"
3. 检查所有 Element Plus 组件的 props 是否有重命名
4. 检查事件名是否有变化
5. 保持组件的功能和 UI 表现完全一致
6. 如果某个属性在 Element Plus 中已废弃,用推荐的替代方案替换
7. 样式相关的类名如果有变化也同步更新
8. 在改动处添加注释说明
请直接输出完整的重构后文件内容。
待重构的组件代码如下:
---
{粘贴你的组件代码}
---
提示词 2:图标批量替换
请帮我将以下代码中所有 ElementUI 的图标使用方式(el-icon-xxx 类名)替换为 Element Plus 的组件式图标写法。 规则: 1. →2. 图标名的转换:el-icon-xxx → 大驼峰命名,例如: - el-icon-edit → Edit - el-icon-delete → Delete - el-icon-search → Search - el-icon-user → User - el-icon-setting → Setting 3. 需要在 script 中 import 对应的图标:import { Edit, Delete } from '@element-plus/icons-vue' 4. 如果是在按钮的 icon 属性中使用( ),改为 :icon="Edit" 5. 保持所有其他代码不变 请输出完整的修改后代码,并列出所有替换的图标清单。 代码如下: --- {粘贴你的代码} ---
提示词 3:SCSS 主题变量迁移
请将以下 SCSS 文件中的 ElementUI 主题变量替换为 Element Plus 的主题变量。
替换规则:
1. $--color-primary → $--el-color-primary(加 el- 前缀)
2. $--color-success → $--el-color-success
3. $--color-warning → $--el-color-warning
4. $--color-danger → $--el-color-danger
5. $--color-info → $--el-color-info
6. 所有 $-- 开头的 ElementUI 变量都加上 el- 前缀,变为 $--el-
7. 检查变量名是否有其他变化(部分变量在 Element Plus 中已重命名)
8. 如果使用了 @import "~element-ui/packages/theme-chalk/src/index"; 改为 Element Plus 的对应引入方式
9. 自定义覆盖变量的写法保持不变
请输出修改后的完整 SCSS 内容。
SCSS 代码如下:
---
{粘贴你的 SCSS 代码}
---
五、Phase 3:Vuex → Pinia
5.1 迁移思路
Pinia 是 Vue3 官方推荐的状态管理库,相比 Vuex 简洁不少,TypeScript 支持也更好。推荐的做法是:
- 先安装 Pinia,让它和 Vuex 共存
- 逐个 module 迁移到 Pinia store
- 组件中逐步替换引用
- 全部迁移完后移除 Vuex
5.2 核心概念映射
Vuex 和 Pinia 的概念对应关系如下:
| Vuex | Pinia | 说明 |
|---|---|---|
state | state | 状态,函数返回对象 |
mutations | 移除,直接修改 state | 不需要 mutations 了 |
actions | actions | 支持同步和异步 |
getters | getters | 计算属性 |
modules | 多个独立的 store | 没有嵌套模块了 |
commit('xxx') | 直接赋值 store.xxx = yyy | 直接修改 |
dispatch('xxx') | store.xxx() | 直接调用方法 |
mapState | storeToRefs() | 解构保持响应式 |
mapGetters | storeToRefs() | 同上 |
mapActions | 直接解构函数 | 函数可直接解构 |
命名空间 namespaced: true | 每个 store 自动独立 | 天然命名空间 |
5.3 Claude Code 提示词:Vuex 转 Pinia
提示词 1:单个 Vuex module 转 Pinia store
你是一个 Pinia 迁移专家。请将以下 Vuex module 重构为 Pinia 的 defineStore 写法,要求:
1. 使用 defineStore 定义 store,id 用原 module 的名称
2. state 保持为函数返回对象,转为箭头函数
3. mutations 全部移除,改为直接在 actions 中修改 state
4. actions 中的方法:
- 移除 context 参数,直接用 this 访问 state 和其他 actions
- 所有 commit('xxx', payload) 改为直接修改 this.state 属性
- 所有 dispatch('xxx', payload) 改为直接调用 this.xxx(payload)
5. getters 保持,用 state 参数访问状态
6. 使用 TypeScript 为 state 添加类型定义
7. 保持所有业务逻辑完全一致
8. 如果有嵌套的子模块,拆分为独立的 store
9. 在关键改动处添加注释
请输出完整的重构后 store 文件内容。
Vuex module 代码如下:
---
{粘贴你的 Vuex module 代码}
---
提示词 2:组件中 Vuex 用法替换为 Pinia
请将以下 Vue 组件中所有 Vuex 的用法替换为 Pinia 的用法,要求:
1. import { mapState, mapGetters, mapActions } from 'vuex' → import { useXxxStore } from '@/stores/xxx'
2. computed 中的 mapState / mapGetters → const store = useXxxStore(); const { xxx, yyy } = storeToRefs(store)
3. methods 中的 mapActions → const { action1, action2 } = useXxxStore()
4. this.$store.state.xxx → store.xxx
5. this.$store.commit('xxx', val) → store.xxx = val 或对应的 action
6. this.$store.dispatch('xxx', val) → store.xxx(val)
7. this.$store.getters.xxx → store.xxx
8. 保持组件功能完全一致
9. 需要 import storeToRefs from 'pinia'
请输出完整的修改后组件代码。
组件代码如下:
---
{粘贴你的组件代码}
---
提示词 3:Vuex 插件/中间件迁移
请将以下 Vuex 插件代码迁移为 Pinia 插件写法,要求:
1. Vuex 插件的 (store) => {} 形式 → Pinia 插件的 ({ store }) => {} 形式
2. store.subscribe → Pinia 的 store.$subscribe
3. store.subscribeAction → Pinia 的 store.$onAction
4. 持久化插件等常用插件,如果有 Pinia 版本建议直接替换(如 pinia-plugin-persistedstate)
5. 保持插件的功能完全一致
6. 添加 TypeScript 类型
请输出迁移后的完整插件代码。
Vuex 插件代码如下:
---
{粘贴你的插件代码}
---
六、Phase 4:Ja vaScript → TypeScript
6.1 迁移思路
TypeScript 迁移是最耗时的阶段,建议从下往上迁移,先把底层基础打好:
- 工具函数 / utils → 最容易,纯函数,几乎没有副作用
- 类型定义 / interfaces → 先定义好共享类型,后面才能复用
- Store(Pinia) → 状态层类型很重要,先搞定
- 组件 → 从简单组件开始,逐步到复杂组件
- 入口文件 / 配置文件 → 最后处理,因为涉及全局类型扩展
6.2 关键类型定义
| 场景 | Vue2 JS | Vue3 TS |
|---|---|---|
| Props | props: ['name', 'age'] | defineProps<{ name: string; age: number }>() |
| Emits | emits: ['update'] | defineEmits<{ (e: 'update', val: string): void }>() |
| Ref | - | const count = ref |
| Reactive | - | const state = reactive |
| Computed | - | const double = computed |
| 组件实例 | this | const instance = getCurrentInstance() |
| 路由 | this.$router | const router = useRouter() |
| 路由参数 | this.$route.params | const route = useRoute(); route.params |
| 全局属性 | this.$xxx | 类型声明扩展 ComponentCustomProperties |
6.3 Claude Code 提示词:JS 转 TS
提示词 1:工具函数 JS → TS
请将以下 Ja vaScript 工具函数文件转换为 TypeScript,要求:
1. 为所有函数参数添加类型注解
2. 为所有函数返回值添加类型注解
3. 为内部变量推断或添加类型
4. 导出的函数和变量都要有明确类型
5. 如果有对象参数,定义对应的 interface 或 type
6. 如果有回调函数,定义函数类型
7. 保持所有逻辑完全不变
8. 尽量利用 TypeScript 的类型推断,不要过度标注
9. 文件扩展名改为 .ts
请输出完整的转换后代码。
JS 代码如下:
---
{粘贴你的 JS 代码}
---
提示词 2:Vue 组件 JS → TS
请将以下 Vue 组件的 Ja vaScript 部分转换为 TypeScript,使用
提示词 3:生成类型定义文件
请根据以下 API 接口的返回数据结构,生成对应的 TypeScript 类型定义文件。
要求:
1. 为每个数据结构定义 interface
2. 嵌套对象也要定义对应的 interface
3. 数组类型明确标注元素类型
4. 可选属性用 标记
5. 枚举值用 enum 或联合类型
6. 接口命名使用大驼峰,语义清晰
7. 加上适当的注释说明
8. 全部 export
API 返回数据示例:
---
{粘贴 API 返回的 JSON 数据或接口文档}
---
七、Phase 5:全面拥抱 Vue3(清理阶段)
7.1 清理清单
当所有模块都迁移完成后,进行最终清理。这一步不能省,否则兼容层会拖累性能:
- 移除
@vue/compat兼容模式 - 移除 Vuex 依赖
- 移除 ElementUI 依赖
- 移除所有
// @ts-ignore和any类型(尽量) - 统一 Composition API 写法,移除 Options API
- 启用严格模式
strict: true - 所有组件都加上
name(可选,Vue3 不再必须) - 全局注册的组件改为按需引入
- 跑通所有测试
- 完整回归测试
7.2 Claude Code 提示词:代码审查与优化
你是一个 Vue3 + TypeScript 代码审查专家。请审查以下 Vue3 组件代码,检查是否存在以下问题并给出优化建议:
1. 是否还有 Vue2 的遗留写法(如 this.$xxx, filters, .sync 等)
2. TypeScript 类型是否完整,有没有 any 或 @ts-ignore
3. Composition API 的使用是否规范
4. 响应式数据的使用是否合理(ref vs reactive 的选择)
5. 有没有可以用 computed 优化的计算逻辑
6. 有没有内存泄漏风险(如未清理的定时器、事件监听)
7. 组件是否可以拆分为更小的组件
8. 命名是否规范
9. 有没有可以用 Vue3 新特性优化的地方(如 teleport, suspense 等)
请按以下格式输出:
## 问题清单
1. [问题类型] 问题描述 → 优化建议
2. ...
## 优化后代码
{完整的优化后代码}
待审查的组件代码:
---
{粘贴你的组件代码}
---
八、完整重构流程 Prompt(一键启动)
如果你想偷个懒,让 Claude Code 直接帮你规划整个重构流程,用这个提示词即可:
你是一位资深的 Vue3 架构师和重构专家。我有一个 Vue2 老项目,需要全面重构为 Vue3 + TypeScript + Element Plus + Pinia。
项目基本情况:
- 项目规模:{填写:小型/中型/大型,约 N 个组件}
- 当前技术栈:Vue 2.x + ElementUI + Vuex + Ja vaScript + {构建工具}
- 项目类型:{管理后台/移动端/官网/其他}
- 是否有测试:{是/否}
- 团队规模:{N 人}
- 期望完成时间:{N 周}
请你:
1. 先帮我制定一个详细的分阶段重构计划,每个阶段包含:
- 阶段目标
- 预计时间
- 具体步骤
- 风险点和应对方案
- 验收标准
2. 给出每个阶段的最佳实践和避坑指南
3. 推荐一些有用的工具和库来辅助迁移
4. 制定一个代码审查 checklist,确保重构质量
请用结构化的方式输出,让我可以直接按照计划执行。
九、常见问题与避坑指南
Q1:重构过程中业务还在迭代怎么办?
A:采用「双轨并行」策略——主分支继续开发新功能(Vue2 版本),重构分支定期从主分支合并,重构完成后一次性切换。或者另一种方式:新功能直接在重构分支用 Vue3 写,老功能逐步迁移。
Q2:第三方组件库不支持 Vue3 怎么办?
A:
- 找 Vue3 替代方案(大部分主流库都有 Vue3 版本)
- 用
@vue/compat兼容模式暂时撑着 - 自己封装适配层
- 实在不行就 fork 一份自己改
Q3:TypeScript 报错太多,改不动怎么办?
A:
- 先开
strict: false,逐步加严格 - 先用
any顶着,后面再补类型 - 从下往上迁移(工具函数 → store → 组件)
- 优先给公共 API 加类型,内部实现可以宽松些
Q4:Element Plus 的组件行为和 ElementUI 不一样怎么办?
A:
- 先查 Element Plus 的 CHANGELOG 和迁移指南
- 用全局配置统一调整默认行为
- 封装一层自定义组件,抹平差异
- 实在不一样的地方,跟产品确认是否接受微调
Q5:重构后性能反而下降了?
A:
- 检查是否有不必要的响应式数据(用
shallowRef/shallowReactive) - 检查 computed 是否有重复计算
- 检查大列表是否用了
v-memo或虚拟滚动 - Vue3 的性能优势在大型应用中更明显,小应用可能感知不到
十、总结
重构路线图回顾
Phase 0: 基础设施准备
↓
Phase 1: Vue2 → Vue3(兼容模式启动)
↓
Phase 2: ElementUI → Element Plus(UI 层统一)
↓
Phase 3: Vuex → Pinia(状态管理升级)
↓
Phase 4: Ja vaScript → TypeScript(类型安全)
↓
Phase 5: 清理兼容层,全面拥抱 Vue3
关键成功因素
- 渐进式:不要追求一步到位,分阶段、按模块迁移
- 可回退:每一步都要能回退,小步快跑
- 测试保障:有测试就跑测试,没测试就写关键路径的测试
- 团队共识:所有人都要了解迁移计划和规范
- AI 辅助:用 Claude Code 处理机械性工作,人来做决策和 review
最后一句话:重构不是目的,提升项目可维护性和开发效率才是目的。不要为了用新技术而重构,要因为重构能带来价值而重构。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。