Vue 3 完整教程
Vue 3 是一个渐进式 JavaScript 框架,用于构建用户界面。本教程将带您从基础到进阶,全面掌握 Vue 3 的核心概念和最佳实践。
什么是 Vue 3?
Vue 3 是 Vue.js 的最新主要版本,带来了许多重要的改进和新特性:
- 🚀 更好的性能 - 更小的包体积,更快的渲染速度
- 🔧 Composition API - 更灵活的逻辑复用方式
- 📦 更好的 TypeScript 支持 - 原生 TypeScript 支持
- 🌳 Tree-shaking 友好 - 按需引入,减少包体积
环境准备
安装 Node.js
确保您的系统已安装 Node.js 16+ 版本:
bash
node --version
npm --version
创建 Vue 3 项目
使用 Vite 创建新项目(推荐):
bash
npm create vue@latest my-vue-app
cd my-vue-app
npm install
npm run dev
或使用 Vue CLI:
bash
npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app
npm run serve
基础概念
1. 模板语法
Vue 使用基于 HTML 的模板语法:
vue
<template>
<div>
<!-- 文本插值 -->
<h1>{{ title }}</h1>
<!-- 属性绑定 -->
<img :src="imageUrl" :alt="imageAlt">
<!-- 事件监听 -->
<button @click="handleClick">点击我</button>
<!-- 条件渲染 -->
<p v-if="isVisible">这段文字是可见的</p>
<!-- 列表渲染 -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
2. 响应式数据
使用 ref
和 reactive
创建响应式数据:
vue
<script setup>
import { ref, reactive } from 'vue'
// 基本类型使用 ref
const count = ref(0)
const message = ref('Hello Vue 3!')
// 对象类型使用 reactive
const user = reactive({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
})
// 修改数据
const increment = () => {
count.value++
}
const updateUser = () => {
user.name = '李四'
user.age = 30
}
</script>
3. 计算属性
使用 computed
创建计算属性:
vue
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('张')
const lastName = ref('三')
// 只读计算属性
const fullName = computed(() => {
return firstName.value + lastName.value
})
// 可写计算属性
const fullNameWritable = computed({
get() {
return firstName.value + lastName.value
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
4. 侦听器
使用 watch
和 watchEffect
侦听数据变化:
vue
<script setup>
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const user = reactive({ name: '张三', age: 25 })
// 侦听单个数据源
watch(count, (newValue, oldValue) => {
console.log(`count 从 ${oldValue} 变为 ${newValue}`)
})
// 侦听多个数据源
watch([count, () => user.name], ([newCount, newName], [oldCount, oldName]) => {
console.log('count 或 user.name 发生了变化')
})
// 立即执行的侦听器
watchEffect(() => {
console.log(`当前 count: ${count.value}`)
})
</script>
组件开发
1. 组件定义
vue
<!-- UserCard.vue -->
<template>
<div class="user-card">
<img :src="user.avatar" :alt="user.name">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<button @click="$emit('follow', user.id)">关注</button>
</div>
</template>
<script setup>
// 定义 props
const props = defineProps({
user: {
type: Object,
required: true
}
})
// 定义 emits
const emit = defineEmits(['follow'])
</script>
<style scoped>
.user-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
text-align: center;
}
</style>
2. 组件使用
vue
<template>
<div>
<UserCard
v-for="user in users"
:key="user.id"
:user="user"
@follow="handleFollow"
/>
</div>
</template>
<script setup>
import UserCard from './components/UserCard.vue'
const users = ref([
{ id: 1, name: '张三', email: 'zhangsan@example.com', avatar: '/avatar1.svg' },
{ id: 2, name: '李四', email: 'lisi@example.com', avatar: '/avatar2.svg' }
])
const handleFollow = (userId) => {
console.log(`关注用户 ${userId}`)
}
</script>
3. 插槽 (Slots)
vue
<!-- Card.vue -->
<template>
<div class="card">
<header class="card-header">
<slot name="header"></slot>
</header>
<main class="card-content">
<slot></slot>
</main>
<footer class="card-footer">
<slot name="footer"></slot>
</footer>
</div>
</template>
使用插槽:
vue
<template>
<Card>
<template #header>
<h2>卡片标题</h2>
</template>
<p>这是卡片的主要内容</p>
<template #footer>
<button>确定</button>
<button>取消</button>
</template>
</Card>
</template>
状态管理
使用 Pinia
安装 Pinia:
bash
npm install pinia
创建 store:
javascript
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', () => {
const user = ref(null)
const isLoggedIn = computed(() => !!user.value)
const login = async (credentials) => {
// 登录逻辑
const response = await api.login(credentials)
user.value = response.data
}
const logout = () => {
user.value = null
}
return {
user,
isLoggedIn,
login,
logout
}
})
在组件中使用:
vue
<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
const handleLogin = async () => {
await userStore.login({
username: 'admin',
password: '123456'
})
}
</script>
路由管理
使用 Vue Router
安装 Vue Router:
bash
npm install vue-router@4
配置路由:
javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User, props: true }
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在组件中使用:
vue
<template>
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</nav>
<router-view />
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const goToUser = (userId) => {
router.push(`/user/${userId}`)
}
</script>
最佳实践
1. 组件设计原则
- 单一职责:每个组件只负责一个功能
- 可复用性:设计通用的组件接口
- 可测试性:编写单元测试
2. 性能优化
vue
<script setup>
import { defineAsyncComponent } from 'vue'
// 异步组件
const AsyncComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
)
// 使用 shallowRef 优化大型对象
import { shallowRef } from 'vue'
const largeData = shallowRef({})
</script>
3. 代码组织
src/
├── components/ # 通用组件
│ ├── ui/ # UI 组件
│ └── business/ # 业务组件
├── views/ # 页面组件
├── stores/ # 状态管理
├── composables/ # 组合式函数
├── utils/ # 工具函数
└── assets/ # 静态资源
常见问题
Q: 什么时候使用 ref,什么时候使用 reactive?
A:
- 基本类型(string、number、boolean)使用
ref
- 对象和数组使用
reactive
- 需要重新赋值整个对象时使用
ref
Q: 如何在 Vue 3 中使用 TypeScript?
A:
vue
<script setup lang="ts">
interface User {
id: number
name: string
email: string
}
const user = ref<User>({
id: 1,
name: '张三',
email: 'zhangsan@example.com'
})
</script>
Q: 如何优化大列表渲染?
A: 使用虚拟滚动或分页,避免一次性渲染大量 DOM 元素。
总结
Vue 3 提供了强大而灵活的开发体验,通过 Composition API 和改进的性能,让我们能够构建更好的应用程序。掌握这些核心概念和最佳实践,您就能够高效地开发 Vue 3 应用。
继续学习: