1. Vue 3 简介与新特性
Vue 3 是一款用于构建用户界面的渐进式 JavaScript 框架。相比于 Vue 2,它在性能、开发体验和类型支持方面都有显著提升。
-
性能提升:打包大小减少 41%,初次渲染快 55%,更新渲染快 133%,内存减少 54%。
-
更好的 TypeScript 支持:Vue 3 本身由 TypeScript 编写,提供了更好的类型推导和开发体验。
-
新特性:引入了 Composition API、Fragment、Teleport、Suspense 等新特性。
-
Vue 2 停止维护:Vue 2 已于 2023 年 12 月 31 日停止维护,官方推荐升级到 Vue 3。
2. 响应式系统
Vue 3 使用 Proxy API 替代了 Vue 2 中的 Object.defineProperty 来实现响应式,解决了 Vue 2 中无法检测数组索引变化和对象属性添加/删除的问题,并提升了性能。
| 特性 | Vue 2 | Vue 3 |
|---|---|---|
| 实现方式 | Object.defineProperty | Proxy |
| 数组检测 | 需要重写数组方法 | 直接支持 |
| 属性增删 | 无法直接检测 | 直接检测 |
| 性能 | 相对较低 | 更高 |
在 Vue 3 中,主要通过 ref和 reactive来创建响应式数据:
-
ref:用于定义基本类型数据(也可以定义对象或数组)。在 JavaScript 中操作需要通过
.value,但在模板中不需要。import { ref } from 'vue'; const count = ref(0); console.log(count.value); // 0 -
reactive:用于定义对象或数组类型数据。直接操作属性即可。
import { reactive } from 'vue'; const state = reactive({ count: 0 }); console.log(state.count); // 0
计算属性 (computed) 和侦听器 (watch, watchEffect) 也是响应式系统的重要组成部分:
-
computed:基于依赖的响应式数据计算并返回一个缓存的值。
import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); -
watch:监听一个或多个响应式数据源的变化,并执行回调函数。
import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newValue, oldValue) => { console.log(`count changed from ${oldValue} to ${newValue}`); }); -
watchEffect:立即运行一个函数,并响应式地追踪其依赖,并在依赖变更时重新执行。
import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => { console.log(`count is: ${count.value}`); });
3. 组合式 API (Composition API)
Composition API 是 Vue 3 的核心新特性,它允许你通过函数形式组织组件逻辑,提高代码的复用性和可维护性,尤其适合复杂组件。
-
setup 函数:Composition API 的“舞台”,组件中使用的数据、方法等都在此配置。它在
beforeCreate之前执行,this为undefined。import { ref } from 'vue'; export default { setup(props, context) { // props 是组件接收的属性 // context 包含 attrs, slots, emit 等 const count = ref(0); function increment() { count.value++; } // 返回的对象中的属性和方法可在模板中使用 return { count, increment }; } }; -
响应式 API:如之前提到的
ref,reactive,computed,watch,watchEffect。 -
生命周期钩子:Composition API 提供了对应的生命周期函数(如
onMounted,onUpdated等),可以在setup中使用。 -
代码复用:通过自定义 Hook 函数来复用逻辑。
// useCounter.js import { ref } from 'vue'; export function useCounter() { const count = ref(0); function increment() { count.value++; } return { count, increment }; } // MyComponent.vue import { useCounter } from './useCounter'; export default { setup() { const { count, increment } = useCounter(); return { count, increment }; } };
4. 生命周期
Vue 3 的生命周期钩子与 Vue 2 相比有一些变化和更名。
| Options API | Composition API | 描述 |
|---|---|---|
beforeCreate | - | 实例初始化后 |
created | - | 实例创建完成 |
beforeMount | onBeforeMount | 挂载之前 |
mounted | onMounted | 挂载完成 |
beforeUpdate | onBeforeUpdate | 数据更新前 |
updated | onUpdated | 数据更新后 |
beforeUnmount | onBeforeUnmount | 卸载之前 |
unmounted | onUnmounted | 卸载完成 |
errorCaptured | onErrorCaptured | 捕获到子孙组件错误时 |
在 setup()函数中使用 Composition API 生命周期钩子:
import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('Component is mounted!');
});
onUnmounted(() => {
console.log('Component is unmounted!');
});
}
};
5. 模板语法与指令
Vue 的模板语法允许你声明式地将数据渲染到 DOM。
-
插值:使用双大括号
{{ }}。<span>{{ message }}</span> -
指令:带有
v-前缀的特殊属性。
| 指令 | 描述 |
|---|---|
v-bind(:) | 动态绑定属性 |
v-on(@) | 绑定事件监听器 |
v-model | 在表单元素上创建双向数据绑定 |
v-if/ v-show | 条件性地渲染元素。v-if是真正的条件渲染;v-show只是切换 displayCSS 属性。 |
v-for | 基于源数据多次渲染元素或模板块。务必指定唯一的 key。 |
v-html | 更新元素的 innerHTML(注意防止 XSS 攻击) |
v-text | 更新元素的 textContent |
v-model的用法:
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
v-for的用法:
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.message }}
</li>
</ul>
6. 组件与通信
组件是 Vue 应用的基石。
-
单文件组件 (SFC):即
.vue文件,包含<template>,<script>,<style>三个部分。<template> <div>{{ msg }}</div> </template> <script> export default { props: ['msg'], setup() { // ... } } </script> <style scoped> /* 样式 */ </style> -
组件通信:
-
Props:父组件向子组件传递数据。
<!-- 父组件 --> <ChildComponent :message="parentMsg" /> <!-- 子组件 --> <script> export default { props: ['message'] } </script> -
自定义事件:子组件向父组件传递消息。
<!-- 子组件 --> <button @click="$emit('enlarge-text')">Enlarge text</button> <!-- 父组件 --> <ChildComponent @enlarge-text="handleEnlargeText" /> -
Provide / Inject:跨层级组件通信。
// 祖先组件 import { provide } from 'vue'; export default { setup() { provide('theme', 'dark'); } }; // 后代组件 import { inject } from 'vue'; export default { setup() { const theme = inject('theme', 'light'); // 'light' 为默认值 return { theme }; } };
-
7. 路由与状态管理
对于单页面应用 (SPA),路由和状态管理几乎是必不可少的。
-
路由 (Vue Router):官方路由管理器。
// router/index.js import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: () => import('../views/About.vue') } // 路由懒加载 ]; const router = createRouter({ history: createWebHistory(), routes }); export default router; // main.js import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; const app = createApp(App); app.use(router); app.mount('#app'); -
状态管理 (Pinia):Vue 3 官方推荐的状态管理库(替代 Vuex)。
Pinia 的 Store 中包含三个概念:
state,getter,action。// stores/counter.js import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), getters: { doubleCount: (state) => state.count * 2 }, actions: { increment() { this.count++; } } }); // 组件中使用 import { useCounterStore } from '@/stores/counter'; export default { setup() { const counterStore = useCounterStore(); return { counterStore }; } };
8. 生态系统与工具
-
构建工具:
-
Vite:新一代前端构建工具,开发环境启动速度极快,推荐用于新项目。
npm create vite@latest my-vue-app -- --template vue cd my-vue-app npm install npm run dev -
Vue CLI:虽然仍可使用,但已处于维护模式。
-
-
UI 框架:可根据项目需求选择:
- Element Plus
- Ant Design Vue
- Naive UI
- TDesign
-
TypeScript 支持:Vue 3 对 TypeScript 提供了更好的支持。
import { defineComponent } from 'vue'; interface User { name: string; age: number; } export default defineComponent({ props: { user: { type: Object as () => User, required: true } }, setup(props) { // props.user 具有 User 类型 } });
9. 性能优化与新特性
Vue 3 在性能方面做了许多改进:
-
Tree-shaking:未引入的 API 在最终打包产物中会被移除,减小体积。
-
静态提升:编译时对静态节点进行提升,减少重渲染时的开销。
-
Fragment:组件可以有多个根节点,无需额外包裹。
-
Teleport:可以将组件的内容渲染到 DOM 树的指定位置,常用于模态框、弹窗等。
<teleport to="body"> <div class="modal"> This modal will be rendered at the bottom of the body. </div> </teleport> -
Suspense:异步组件加载时显示占位内容(实验性特性)。
<Suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <div>Loading...</div> </template> </Suspense>