文章目录
- 前言
- 0.迁移过程
- 1. 安装 Vue 3
- 2. 逐一处理迁移中的警告
- 3. 迁移全局和内部 API
- 4. 迁移 Vue Router 和 Vuex
- 5. 处理其他的不兼容变更
- 1. Vue3特性
- 1. Composition API
- 2. 更好的性能
- 3. 更好的 TypeScript 支持
- 4. 多个根元素
- 5. Suspense 组件
- 6. Teleport 组件
- 7. 全局 API 的改变
- 8. 自定义渲染器 API
- 2.修改清单
- 1.模板指令
- 2. v-model
- 3. key 使用改变
- 4. **v-if 与 v-for 优先级
- 5. v-bind 合并行为
- 6. **v-on.native 移除**:
- 8. 函数式组件
- 9. **异步组件**:
- 10. **emits 选项**:
- 11. **渲染函数**:
- 12. **移除的 APIs**:
- 13. **按键修饰符**:
- 14. **事件 API**:
- 15. **过滤器**:
- 16. **内联模板**:
- 17. **$children**:
- 18. **propsData 选项**:
- 19. **Attribute 强制行为**:
- 20. **自定义指令**:
- 21. **Data 选项**:
- 22. **Mount API 的改变**:
- 23. **Props 的默认函数访问 this**:
- 24. **Transition class 名更改**:
- 25. **Transition 作为根节点**:
- 26. **TransitionGroup 根元素**:
- 27. **VNode 生命周期事件**:
- 28. **Watch 侦听数组**:
- 参考资料
前言
背景:有同学说我上一篇《Vue 2.x 项目升级到 Vue 3详细指南【总结版】》看的太费劲,让我直接整理一篇
Vue2.x 升级到 vue3 的修改清单
,所以整理了此文章。
Vue 3.0 已经发布,很多人可能都在疑惑如何将自己的 Vue 2.x 项目升级到 Vue 3.0。这篇文章将详细地介绍这个过程。它引入了许多新特性和改进,包括更好的性能、更小的包大小、更好的 TypeScript 支持,以及新的 API,如 Composition API。
从 Vue 2.x 升级到 Vue 3 并不是一个简单的任务,因为 Vue 3 引入了一些重大的不兼容变更。这些变更可能会影响你的应用的行为,或者需要你修改你的代码以适应新的 API。
在开始升级之前,我建议你先备份你的项目,或者使用版本控制系统,如Git,以便在需要时可以轻松地回滚到旧版本。此外,你应该确保你的项目的所有依赖项都已经支持 Vue 3,或者至少有可用的替代方案。
现在,让我们开始升级你的 Vue 2.x 项目到 Vue 3 吧!go go
0.迁移过程
1. 安装 Vue 3
首先,你需要安装 Vue 3 到你的项目。你可以通过 npm 或 yarn 来进行安装:
npm install vue@next
# 或者
yarn add vue@next
2. 逐一处理迁移中的警告
Vue 3 在兼容性构建中为大部分的有破坏性的改动提供了运行时警告。在你完成初始升级之后,你可以根据运行时控制台中的警告提示逐一处理新代码中的问题。
3. 迁移全局和内部 API
Vue 3 的全局 API 发生了一些改变,如Vue.prototype 被改为 config.globalProperties,Vue.mixin() 现在只适用在应用的根组件,而非全局。这些全局 API 的改变都需要在迁移时被处理和修改。
4. 迁移 Vue Router 和 Vuex
Vue Router 和 Vuex 在 Vue 3 中也有一些改变。你需要安装 vue-router@4 和 vuex@next 并根据相应文档进行迁移。
5. 处理其他的不兼容变更
Vue 3 有一些其他的不兼容变更,如新的生命周期函数名称、更改的事件行为、移除的 filters 等。你需要查阅迁移指南,了解如何处理这些不兼容变更。
1. Vue3特性
在说升级之前 我们先来了解一下。Vue 3 引入了许多新特性和改进,以下是一些主要的亮点:
1. Composition API
这是 Vue 3 的一项主要新特性,它提供了一种新的方式来组织和复用代码。与 Vue 2 的 Options API 相比,Composition API 提供了更好的类型推断,使得 Vue 更易于与 TypeScript 一起使用。
import { ref, computed } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => { count.value++ };
const decrement = () => { count.value-- };
const isEven = computed(() => count.value % 2 === 0);
return {
count,
increment,
decrement,
isEven
};
}
};
2. 更好的性能
Vue 3 的虚拟 DOM 重写和优化,使得渲染速度比 Vue 2 快约 1.3 到 2 倍。此外,Vue 3 的包大小比 Vue 2 小约 10%。
3. 更好的 TypeScript 支持
Vue 3 的源代码完全用 TypeScript 重写,这使得 Vue 3 与 TypeScript 的集成更加紧密,提供了更好的类型推断和编辑器支持。
4. 多个根元素
vue 3 允许在单文件组件中使用多个根元素,这使得组件的结构更加灵活。
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>
5. Suspense 组件
Vue 3 引入了新的 Suspense
组件,用于处理异步组件的加载状态。这使得你可以在异步组件加载完成之前显示一个加载指示器,或者在加载失败时显示一个错误消息。
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
6. Teleport 组件
Vue 3 引入了新的 Teleport
组件,用于将子组件渲染到 DOM 树的其他位置。这对于实现模态对话框、通知、弹出菜单等功能非常有用。
<Teleport to="#modal-container">
<div class="modal">...</div>
</Teleport>
7. 全局 API 的改变
Vue 3 对全局 API 进行了重大的改变,以使其更加模块化和树摇优化友好。例如,Vue.component
、Vue.directive
等全局 API 在 Vue 3 中被移除,取而代之的是 app.component
、app.directive
等实例方法。
8. 自定义渲染器 API
Vue 3 提供了一个新的自定义渲染器 API,使得你可以创建自己的渲染器,例如用于创建原生移动应用的渲染器。
2.修改清单
我们需要按照以下方式将项目中使用到地方进行修改。以进行适配。
1.模板指令
Vue 3 对多个模板指令进行了更新,包括 v-model
,v-if
/v-for
,v-bind
等。这意味着这些指令的行为可能与 Vue 2 不同,你需要检查你的代码以确保它们与新的行为保持一致。
2. v-model
在 Vue 3 中,v-model
的行为和语法发生了变化。现在,你需要使用 v-model:[argument]="data"
的形式来绑定数据,而不是 Vue 2 中的 v-model="data"
。
<!-- Vue 2 -->
<input v-model="message" />
<!-- Vue 3 -->
<input v-model:value="message" />
3. key 使用改变
在 Vue 3 中,key
的使用方式发生了变化。现在,v-for
中的 key
是必须的。这意味着你需要在所有的 v-for
指令中添加 key
。
<!-- Vue 2 -->
<div v-for="item in items">
{{ item }}
</div>
<!-- Vue 3 -->
<div v-for="item in items" :key="item.id">
{{ item }}
</div>
4. **v-if 与 v-for 优先级
在 Vue 3 中,v-if
和 v-for
在同一个元素上的优先级发生了变化。现在,v-if
的优先级高于 v-for
。这意味着如果你在同一个元素上使用了这两个指令,你需要确保它们的使用是正确的。
<!-- Vue 2 -->
<div v-for="item in items" v-if="item.isActive">
{{ item }}
</div>
<!-- Vue 3 -->
<div v-for="item in items" :key="item.id">
<div v-if="item.isActive">
{{ item }}
</div>
</div>
5. v-bind 合并行为
Vue 3 改变了 v-bind
的合并行为。在 Vue 2 中,如果你有多个 v-bind
,它们会被合并。但在 Vue 3 中,后面的 v-bind
会覆盖前面的。
<!-- Vue 2 -->
<div v-bind="{ id: 'foo' }" v-bind="{ id: 'bar' }"></div> <!-- id is 'foo' -->
<!-- Vue 3 -->
<div v-bind="{ id: 'foo' }" v-bind="{ id: 'bar' }"></div> <!-- id is 'bar' -->
6. v-on.native 移除:
Vue 3 移除了 v-on.native
修饰符。你需要更新你的代码,移除所有的 .native
修饰符,并使用新的 emits
选项。
<!-- Vue 2 -->
<my-component @click.native="doSomething"></my-component>
<!-- Vue 3 -->
<my-component @click="doSomething"></my-component>
8. 函数式组件
Vue 3 更改了函数式组件的写法,不再需要 functional
关键词。你需要更新你的函数式组件以适应新的写法。
<!-- Vue 2 -->
Vue.component('my-component', {
functional: true,
// ...
})
<!-- Vue 3 -->
const MyComponent = (props, { slots }) => {
// ...
}
9. 异步组件:
Vue 3 改变了异步组件的语法。你需要将你的异步组件语法更新为新的语法。
<!-- Vue 2 -->
Vue.component('my-component', () => import('./MyComponent.vue'))
<!-- Vue 3 -->
const MyComponent = defineAsyncComponent(() => import('./MyComponent.vue'))
10. emits 选项:
Vue 3 添加了全新的 emits
选项,用于定义组件发出的事件。你需要在你的组件中添加 emits
选项。
<!-- Vue 3 -->
export default {
emits: ['my-event'],
methods: {
doSomething() {
this.$emit('my-event')
}
}
}
11. 渲染函数:
Vue 3 的渲染函数 API 有所改变。你需要更新你的渲染函数以适应新的 API。
<!-- Vue 2 -->
Vue.component('my-component', {
render: function (createElement) {
return createElement('div', this.$slots.default)
}
})
<!-- Vue 3 -->
const MyComponent = {
render() {
return h('div', this.$slots.default())
}
}
12. 移除的 APIs:
Vue 3 移除了一些不再需要的 APIs,例如 Vue.set
,Vue.delete
和 Vue.observable
。这些API在Vue.js 2.x中用于添加响应式属性到对象或删除属性,Vue 3中的响应式系统使用 Proxy,所以这些API不再需要。
// Vue 2
Vue.set(object, propertyName, value);
Vue.delete(object, propertyName);
Vue.observable(object);
// Vue 3
// 整个对象都是响应式的,不需要特定的API
13. 按键修饰符:
Vue 3 不再支持按键修饰符的别名,例如 @keyup.enter
,@keyup.space
等。你需要将这些修饰符替换为它们的键码。
<!-- Vue 2 -->
<input @keyup.enter="submit">
<!-- Vue 3 -->
<input @keyup.13="submit">
14. 事件 API:
Vue 3 的事件 API 有所改变,例如 $on
,$off
和 $once
已被移除。你需要使用新的事件 API。
// Vue 2
this.$on('event', handler);
this.$off('event', handler);
this.$once('event', handler);
// Vue 3
// 使用事件发射器如mitt或tiny-emitter
15. 过滤器:
Vue 3 不再支持过滤器。你需要将过滤器替换为计算属性或者方法。
<!-- Vue 2 -->
{{ message | filterA | filterB }}
<!-- Vue 3 -->
{{ filterB(filterA(message)) }}
16. 内联模板:
Vue 3 不再支持内联模板。你需要将内联模板替换为 render
函数或者 template
。
<!-- Vue 2 -->
<my-component inline-template>
<div>{{ message }}</div>
</my-component>
<!-- Vue 3 -->
<my-component>
<template #default="{ message }">
<div>{{ message }}</div>
</template>
</my-component>
17. $children:
Vue 3 不再支持 $children
。你需要找到其他方式来访问子组件。要访问子组件,可以使用 ref
和 provide/inject
。
<!-- Vue 2 -->
this.$children;
<!-- Vue 3 -->
// 使用 ref 或 provide/inject 访问子组件
18. propsData 选项:
Vue 3 不再支持 propsData
选项。你需要在创建组件实例时直接传递 props
。
// Vue 2
new Vue({
propsData: {
prop: value,
},
});
// Vue 3
createApp({
props: {
prop: value,
},
});
19. Attribute 强制行为:
Vue 3 现在默认将未声明的 attribute 视为 DOM attribute。如果你需要强制 attribute 来响应化,你需要使用 v-bind
。
<!-- Vue 2 -->
<my-component my-attr="value" />
<!-- Vue 3 -->
<my-component v-bind="{ 'my-attr': 'value' }" />
20. 自定义指令:
Vue 3 的自定义指令 API 有所改变。你需要更新你的自定义指令以适应新的 API。
// Vue 2
Vue.directive('my-directive', {
bind(el, binding, vnode, oldVnode) { /* ... */ },
update(el, binding, vnode, oldVnode) { /* ... */ },
});
// Vue 3
const myDirective = {
beforeMount(el, binding, vnode, prevVnode) { /* ... */ },
updated(el, binding, vnode, prevVnode) { /* ... */ },
};
21. Data 选项:
Vue 3 的 data
选项必须是一个函数。你需要将所有的 data
选项转换为函数。
// Vue 2
new Vue({
data: {
message: 'Hello Vue!',
},
});
// Vue 3
createApp({
data() {
return {
message: 'Hello Vue!',
};
},
});
22. Mount API 的改变:
Vue 3 的 mount
API 有所改变。你需要更新你的 mount
调用以适应新的 API。
// Vue 2
new Vue({
/* options */
}).$mount('#app');
// Vue 3
createApp({
/* options */
}).mount('#app');
23. Props 的默认函数访问 this:
Vue 3 不再允许在 props 的默认函数中访问 this
。你需要找到其他方式来获取需要的数据。
// Vue 2
props: {
prop: {
default: function () {
return this.someData;
},
},
};
// Vue 3
props: {
prop: {
default() {
// "this" 是 undefined
},
},
};
24. Transition class 名更改:
Vue 3 更改了 transition 的 class 名称,为了与 CSS 动画一致,v-enter
改为了 v-enter-from
,v-leave
改为了 v-leave-from
。
/* Vue 2 */
.fade-enter, .fade-leave-to {
opacity: 0;
}
/* Vue 3 */
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
25. Transition 作为根节点:
Vue 3 不再允许 transition 作为根节点。你需要确保你的组件有一个非 transition 的根节点。
<!-- Vue 2 -->
<transition>
<div>...</div>
</transition>
<!-- Vue 3 -->
<!-- transition 不能作为根节点 -->
<div>
<transition>
<div>...</div>
</transition>
</div>
26. TransitionGroup 根元素:
Vue 3 的 TransitionGroup
不再渲染一个默认的根元素。你需要手动添加一个根元素。
<!-- Vue 2 -->
<transition-group>
<div v-for="item in items" :key="item.id">{{ item }}</div>
</transition-group>
<!-- Vue 3 -->
<transition-group>
<div>
<div v-for="item in items" :key="item.id">{{ item }}</div>
</div>
</transition-group>
27. VNode 生命周期事件:
Vue 3 的 VNode 生命周期事件有所改变。你需要更新你的代码以适应新的事件。
// Vue 2
vnode.context.$on('hook:updated', handler);
// Vue 3
onUpdated(handler);
28. Watch 侦听数组:
Vue 3 的 watch
对于数组的行为有所改变。你需要更新你的 watch
调用以适应新的行为。
// Vue 2
watch(() => [...array], handler);
// Vue 3
watch(() => array, handler, { deep: true });
参考资料
-
Vue 3 Migration Guide - Vue 官方提供的迁移指南,详细介绍了从 Vue 2 到 Vue 3 的各种改变和升级策略。
-
Vue 3 Upgrade Guide - 这篇博客文章详细介绍了 Vue 2 到 Vue 3 的升级过程,包括实践技巧和遇到的问题。