1. 引言
Vue 3 是 Vue.js 框架的第三个大版本,于 2020 年 9 月正式发布。相比 Vue 2,Vue 3 在性能、体积、TypeScript 支持以及组合式 API 等方面带来了革命性的变化。本文将从核心特性、响应式原理、组合式 API、新内置组件、工程化实践等多个维度,带你系统性地掌握 Vue 3。
2. Vue 3 的核心特性
2.1 更快的性能
Vue 3 重写了虚拟 DOM 的实现,采用基于 Proxy 的响应式系统,并引入了静态标记(Patch Flag)与静态提升(Hoisting)等编译优化手段,使得首次渲染和更新渲染的性能都大幅提升。
2.2 更小的体积
Vue 3 将核心功能拆分为多个独立模块,支持 Tree-Shaking。未使用的 API 会在打包时被自动剔除,使得基础包体积相比 Vue 2 减少了约 50%。
2.3 更好的 TypeScript 支持
Vue 3 的源码本身使用 TypeScript 编写,提供了完整的类型推导能力。配合 defineComponent 与组合式 API,开发者可以轻松获得完善的类型提示。
2.4 组合式 API(Composition API)
组合式 API 是 Vue 3 最核心的语法革新,它允许开发者按逻辑关注点组织代码,替代 Vue 2 中按选项(data、methods、computed)组织代码的方式,显著提升了大型项目的可维护性。
3. 响应式原理深入
3.1 从 Object.defineProperty 到 Proxy
Vue 2 使用 Object.defineProperty 拦截对象的属性读写,存在无法监听新增属性、删除属性以及数组索引变化等局限。Vue 3 改用 ES6 的 Proxy 代理整个对象,能够拦截对象的所有操作,包括属性新增、删除、数组下标赋值等,响应式能力更加完整。
3.2 响应式 API 一览
javascript
import { ref, reactive, computed, watch, watchEffect } from 'vue'
// ref:包装基本类型
const count = ref(0)
count.value++
// reactive:包装对象
const state = reactive({ name: 'Vue', version: 3 })
// computed:计算属性
const double = computed(() => count.value * 2)
// watch:监听变化
watch(count, (newVal, oldVal) => {
console.log('count 变化:', newVal, oldVal)
})
// watchEffect:自动追踪依赖
watchEffect(() => {
console.log('当前 count 为:', count.value)
})
3.3 ref 与 reactive 的选择
ref适合包装基本类型(number、string、boolean),也常用于包装需要整体替换的引用类型。reactive适合包装深层嵌套的对象,但直接整体替换对象会丢失响应式,此时应改用ref。- 在模板中,
ref会自动解包,无需写.value;在 JavaScript 逻辑中则需要显式访问.value。
4. 组合式 API 详解
4.1 setup 函数
setup 是组合式 API 的入口,在组件创建之前执行,此时 this 不可用。它接收 props 和 context 两个参数,返回的对象会暴露给模板使用。
vue
<script>
import { ref } from 'vue'
export default {
setup(props, context) {
const message = ref('Hello Vue 3')
const handleClick = () => {
message.value = '你点击了按钮'
}
return { message, handleClick }
}
}
</script>
4.2 script setup 语法糖
<script setup> 是 Vue 3.2 引入的语法糖,它让组合式 API 的写法更加简洁,无需手动 return,顶层变量和函数自动暴露给模板。
vue
<script setup>
import { ref } from 'vue'
const message = ref('Hello Vue 3')
const handleClick = () => {
message.value = '你点击了按钮'
}
</script>
<template>
<button @click="handleClick">{{ message }}</button>
</template>
4.3 逻辑复用:自定义 Hook
组合式 API 最大的优势在于逻辑复用。我们可以把一段有状态的逻辑封装成函数,在多个组件中复用。
javascript
// useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initial = 0) {
const count = ref(initial)
const double = computed(() => count.value * 2)
const increment = () => count.value++
const decrement = () => count.value--
return { count, double, increment, decrement }
}
vue
<script setup>
import { useCounter } from './useCounter'
const { count, double, increment, decrement } = useCounter(10)
</script>
5. 生命周期钩子
Vue 3 的生命周期钩子与 Vue 2 对应关系如下:
| Vue 2 选项式 | Vue 3 组合式 | 触发时机 |
|---|---|---|
| beforeCreate | setup() | 组件实例初始化前 |
| created | setup() | 组件实例创建完成 |
| beforeMount | onBeforeMount | 挂载前 |
| mounted | onMounted | 挂载完成 |
| beforeUpdate | onBeforeUpdate | 数据更新前 |
| updated | onUpdated | 数据更新后 |
| beforeUnmount | onBeforeUnmount | 卸载前 |
| unmounted | onUnmounted | 卸载完成 |
vue
<script setup>
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
console.log('组件已挂载')
})
onUnmounted(() => {
console.log('组件已卸载')
})
</script>
6. 新内置组件
6.1 Fragment(片段)
Vue 3 支持组件拥有多个根节点,不再像 Vue 2 那样强制要求单一根元素。
vue
<template>
<header>顶部</header>
<main>主体</main>
<footer>底部</footer>
</template>
6.2 Teleport(传送门)
Teleport 可以将组件内容渲染到 DOM 中的任意位置,常用于实现模态框、弹窗等需要脱离当前组件层级的场景。
vue
<template>
<teleport to="body">
<div class="modal">这是一个模态框</div>
</teleport>
</template>
6.3 Suspense(异步组件)
Suspense 用于处理异步组件的加载状态,可以在异步组件加载完成前显示占位内容。
vue
<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</template>
7. 工程化实践
7.1 使用 Vite 创建项目
Vite 是 Vue 官方推荐的构建工具,基于原生 ES 模块,开发启动速度极快。
bash
# 使用 npm
npm create vue@latest
# 使用 pnpm
pnpm create vue@latest
7.2 项目目录结构
my-vue-app/
├── src/
│ ├── components/ # 公共组件
│ ├── views/ # 页面组件
│ ├── router/ # 路由配置
│ ├── stores/ # Pinia 状态管理
│ ├── composables/ # 组合式函数
│ ├── assets/ # 静态资源
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── index.html
├── vite.config.js
└── package.json
7.3 状态管理:Pinia
Pinia 是 Vue 3 官方推荐的状态管理库,相比 Vuex 更加轻量,且天然支持组合式 API 和 TypeScript。
javascript
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
vue
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<button @click="counter.increment()">{{ counter.count }}</button>
</template>
7.4 路由:Vue Router 4
Vue Router 4 是 Vue 3 配套的路由库,API 与 Vue Router 3 基本一致,但全面支持组合式 API。
javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: () => import('../views/About.vue') }
]
})
export default router
8. 总结
Vue 3 通过 Proxy 响应式系统、组合式 API、编译优化和全新的生态工具链,为现代前端开发提供了更高效、更灵活的解决方案。无论是新项目选型还是旧项目升级,Vue 3 都值得优先考虑。建议读者从组合式 API 入手,配合 Vite、Pinia、Vue Router 4 构建完整的工程化项目,在实践中逐步深入。