最近在将一个运行了3年的Vue2项目升级到Vue3,过程中踩了不少坑,在此记录一下。
一、生命周期钩子
1. 被移除的钩子
beforeDestroy
→ 改用beforeUnmount
destroyed
→ 改用unmounted
2. 组合式API中的异步陷阱
// 错误示例:在setup中直接调用异步钩子
setup() {
onMounted(async () => {
await fetchData(); // 可能导致内存泄漏
});
}
// 正确方案:分离异步逻辑
setup() {
const loadData = async () => { /* ... */ };
onMounted(() => {
loadData();
});
}
二、模板语法
1. v-model的破坏性变更
<!-- Vue 2:value + @input -->
<Child v-model="pageTitle" />
<!-- Vue 3:modelValue + update:modelValue -->
<Child v-model:title="pageTitle" />
<!-- 多v-model支持 -->
<Form v-model:name="name" v-model:age="age" />
2. 事件监听符的变更
<!-- Vue 2监听原生事件 -->
<comp @click.native="handleClick" />
<!-- Vue 3移除.native -->
<comp @click="handleClick" />
<!-- 需要传递原生事件时 -->
<comp v-on="listeners" />
三、全局API
1. Vue.prototype的替代方案
// Vue 2全局挂载
Vue.prototype.$http = axios;
// Vue 3使用provide/inject
// main.js
app.provide('http', axios);
// 组件中获取
const http = inject('http');
2. 过滤器(Filter)的废弃处理
// 旧版过滤器
{{ price | currency }}
// 替代方案:全局方法/计算属性
// 注册全局方法
app.config.globalProperties.$currency = (val) => `¥${val}`;
// 模板中使用
{{ $currency(price) }}
四、第三方库的兼容性问题
1. elementUI的版本适配
# Element UI → Element Plus
npm uninstall element-ui
npm install element-plus @element-plus/icons-vue
# 按需引入配置变更
// vite.config.js
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
plugins: [
AutoImport({ resolvers: [ElementPlusResolver()] }),
Components({ resolvers: [ElementPlusResolver()] })
]
2. Vuex到Pinia的迁移
// Vuex模块化
const moduleA = {
state: () => ({ count: 0 }),
mutations: { increment(state) { state.count++ } }
}
// Pinia等效实现
export const useStore = defineStore('moduleA', {
state: () => ({ count: 0 }),
actions: {
increment() { this.count++ }
}
});
五、项目配置
1. Vue CLI到Vite的迁移
// 旧版vue.config.js → vite.config.ts
// 路径别名配置变更
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}
// 环境变量前缀变更
// 原process.env → import.meta.env
VITE_API_URL=xxx # .env文件需以VITE_开头
2. IE11兼容性处理
# 安装polyfill
npm install @vitejs/plugin-legacy --save-dev
# vite.config.js
import legacy from '@vitejs/plugin-legacy';
plugins: [
legacy({
targets: ['defaults', 'not IE 11'] // 明确放弃IE11
})
]