与Vue2架构的主要区别
响应式系统的重构
Vue3 使用 Proxy 替代了 Vue2 的 Object.defineProperty 实现响应式。Proxy 可以拦截整个对象,不需要递归遍历所有属性,性能更好。Vue2 中需要显式调用 Vue.set 来添加新属性响应式,而 Vue3 中直接赋值即可。
// Vue2
this.$set(this.someObject, 'newProperty', value)
// Vue3
this.someObject.newProperty = value // 自动响应
Proxy 还能检测到数组索引变化和 length 变化,Vue2 中需要重写数组方法来实现响应式。Vue3 的响应式系统还支持 Map、Set 等集合类型。
Composition API 的引入
Vue3 新增了 Composition API,作为 Options API 的补充。Composition API 通过 setup 函数组织代码,相关逻辑可以集中在一起,而不是分散在 data、methods 等选项中。
// Vue2 Options API
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
// Vue3 Composition API
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
}
Composition API 更适合复杂组件,逻辑可以提取为可复用的函数,解决了 Vue2 中 mixins 的命名冲突和来源不清晰问题。
虚拟 DOM 的优化
Vue3 重写了虚拟 DOM 的实现,引入了静态提升和补丁标志等优化。模板中的静态节点会被提升到渲染函数外,避免重复创建。编译器会分析动态绑定,生成带有补丁标志的代码,运行时可以跳过静态子树。
// 编译后的渲染函数示例
function render() {
return (_openBlock(), _createBlock("div", null, [
_createVNode("h1", null, "Static Title"), // 静态提升
_createVNode("p", { class: _ctx.dynamicClass }, _toDisplayString(_ctx.message), 1 /* TEXT */)
]))
}
Vue3 还支持片段(Fragment),组件可以有多个根节点,不再需要额外包裹 div。
性能提升
Vue3 在多个方面进行了性能优化:
- 更小的包体积:Tree-shaking 支持更好,未使用的 API 不会打包
- 更快的初始渲染:编译器优化减少了约 40% 的运行时开销
- 更低的内存占用:响应式系统更高效
- 更快的更新:靶向更新只处理动态部分
TypeScript 支持
Vue3 使用 TypeScript 重写,提供了更好的类型推断。Composition API 的设计考虑了类型推导,ref 和 reactive 都有完整的类型支持。
import { ref } from 'vue'
const count = ref(0) // Ref<number>
count.value = 'string' // 类型错误
Vue2 虽然也能用 TypeScript,但需要额外装饰器或 class 组件,类型支持不完整。
自定义渲染器 API
Vue3 将核心逻辑与 DOM 渲染分离,暴露了自定义渲染器 API。可以基于相同响应式系统构建非 DOM 环境的渲染器,如小程序、Canvas 或原生应用。
import { createRenderer } from 'vue'
const { render, createApp } = createRenderer({
patchProp,
insert,
remove,
createElement
// ...其他平台特定方法
})
全局 API 变更
Vue3 调整了全局 API 的组织方式,改为应用实例 API。Vue2 的全局配置会影响所有实例,而 Vue3 每个应用有独立配置。
// Vue2
Vue.config.ignoredElements = [/^app-/]
Vue.directive('focus', { /* ... */ })
// Vue3
const app = createApp(App)
app.config.isCustomElement = tag => tag.startsWith('app-')
app.directive('focus', { /* ... */ })
生命周期调整
Vue3 的生命周期有所变化,beforeDestroy 改为 beforeUnmount,destroyed 改为 unmounted。新增了 renderTracked 和 renderTriggered 调试钩子。
export default {
setup() {
onMounted(() => {
console.log('组件挂载')
})
onUnmounted(() => {
console.log('组件卸载')
})
}
}
模板指令变化
v-model 进行了重大调整,支持多个 v-model 绑定,默认使用 modelValue 替代 value:
<!-- Vue2 -->
<input v-model="message">
<!-- Vue3 默认 -->
<input v-model="message">
<!-- 多个 v-model -->
<CustomComponent v-model:title="title" v-model:content="content" />
v-for 的 key 现在应该放在 template 标签上,而不是子元素。v-if 和 v-for 的优先级也发生了变化,v-if 现在有更高优先级。
异步组件改进
Vue3 提供了 defineAsyncComponent 方法来定义异步组件,支持更灵活的加载状态处理:
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Foo.vue'),
loadingComponent: LoadingComponent,
errorComponent: ErrorComponent,
delay: 200,
timeout: 3000
})
相比 Vue2 的简单函数形式,Vue3 的异步组件配置更丰富。
Teleport 组件
新增 <teleport>
组件(原名为 portal),可以将子组件渲染到 DOM 中的其他位置,适合模态框、通知等需要突破层级限制的场景。
<teleport to="body">
<div class="modal" v-if="showModal">
Modal Content
</div>
</teleport>
Suspense 组件
实验性的 <suspense>
组件可以协调多个嵌套异步依赖的加载状态,在等待异步组件或 async setup 时显示备用内容。
<suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
Loading...
</template>
</suspense>
单文件组件改进
Vue3 的单文件组件支持多个根节点,style 标签现在可以包含全局规则或作用域规则。script 部分可以使用 Composition API 的 setup 语法糖:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
<style scoped>
button {
color: red;
}
</style>
自定义元素交互
Vue3 提供了更好的 Web Components 支持,通过 defineCustomElement 方法可以将 Vue 组件转换为自定义元素:
import { defineCustomElement } from 'vue'
const MyVueElement = defineCustomElement({
props: { msg: String },
template: `<div>{{ msg }}</div>`
})
customElements.define('my-vue-element', MyVueElement)
编译器优化标志
Vue3 的模板编译器会生成带有优化提示的代码,运行时可以根据这些提示进行更高效的更新。例如标记静态节点、动态 props 等:
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("span", { class: _ctx.class }, null, 2 /* CLASS */)
]))
}
过渡动画变化
transition 组件相关类名变更,v-enter 改为 v-enter-from,v-leave 改为 v-leave-from。新增了 transition 作为根组件的过渡效果。
<transition name="fade">
<div v-if="show">Content</div>
</transition>
<style>
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
</style>
事件 API 调整
Vue3 移除了 $on、$off 和 $once 方法,推荐使用外部库实现事件总线。emit 现在需要在 emits 选项中声明,提供更好的文档化和类型检查。
export default {
emits: ['submit'], // 显式声明
setup(props, { emit }) {
const onSubmit = () => {
emit('submit', payload)
}
}
}
插件系统变化
Vue3 的插件安装方式改变,不再调用 Vue.use(),而是在应用实例上调用 use() 方法:
// Vue2
Vue.use(MyPlugin)
// Vue3
const app = createApp(App)
app.use(MyPlugin)
插件定义也相应调整,install 方法接收应用实例而非 Vue 构造函数。
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn