Vue 3 详细教程
一、Vue 3 简介
Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。Vue 3 是 Vue.js 的最新主要版本,于 2020 年 9 月正式发布,带来了许多改进和新特性。
Vue 3 主要新特性
- Composition API - 更灵活的逻辑组织和复用方式
- 性能提升 - 更快的渲染速度和更小的包体积
- 更好的 TypeScript 支持 - 完全使用 TypeScript 重写
- 新的响应式系统 - 基于 Proxy 的响应式实现
- Fragment、Teleport、Suspense - 新的内置组件
二、环境搭建
1. 使用 Vue CLI 创建项目
npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app
npm run serve
2. 使用 Vite 创建项目(推荐)
npm create vite@latest my-vue-app --template vue
cd my-vue-app
npm install
npm run dev
三、基础语法
1. 模板语法
运行
<template>
<div>
<!-- 文本插值 -->
<h1>{{ message }}</h1>
<!-- 属性绑定 -->
<div :id="dynamicId"></div>
<!-- 事件绑定 -->
<button @click="handleClick">点击</button>
<!-- 双向绑定 -->
<input v-model="inputText">
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue 3!',
dynamicId: 'app-container',
inputText: ''
}
},
methods: {
handleClick() {
console.log('按钮被点击了');
}
}
}
</script>
2. 选项式 API vs 组合式 API
选项式 API (Options API)
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
console.log('组件已挂载')
}
}
组合式 API (Composition API)
import { ref, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
function increment() {
count.value++
}
onMounted(() => {
console.log('组件已挂载')
})
return {
count,
increment
}
}
}
四、核心概念
1. 响应式基础
ref 和 reactive
import { ref, reactive } from 'vue'
export default {
setup() {
// ref 用于基本类型
const count = ref(0)
// reactive 用于对象
const state = reactive({
name: 'Vue',
version: 3
})
return {
count,
state
}
}
}
计算属性
import { ref, computed } from 'vue'
export default {
setup() {
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`
})
return {
firstName,
lastName,
fullName
}
}
}
侦听器
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(`count 从 ${oldValue} 变为 ${newValue}`)
})
return {
count
}
}
}
2. 生命周期钩子
选项式 API | 组合式 API | 描述 |
---|---|---|
beforeCreate | - | 实例初始化后 |
created | - | 实例创建完成后 |
beforeMount | onBeforeMount | 挂载开始之前 |
mounted | onMounted | 挂载完成后 |
beforeUpdate | onBeforeUpdate | 数据更新前 |
updated | onUpdated | 数据更新后 |
beforeUnmount | onBeforeUnmount | 实例卸载前 |
unmounted | onUnmounted | 实例卸载后 |
3. 组件通信
Props
// 子组件
export default {
props: {
title: {
type: String,
required: true
}
},
setup(props) {
console.log(props.title)
}
}
// 父组件
<ChildComponent title="Hello from parent" />
自定义事件
// 子组件
export default {
setup(props, { emit }) {
const handleClick = () => {
emit('custom-event', 'some data')
}
return {
handleClick
}
}
}
// 父组件
<ChildComponent @custom-event="handleEvent" />
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
}
}
}
4. 内置组件
Teleport
运行
<teleport to="body">
<div class="modal">
这是一个模态框
</div>
</teleport>
Suspense
运行
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
五、进阶特性
1. 自定义指令
// 全局指令
app.directive('focus', {
mounted(el) {
el.focus()
}
})
// 局部指令
export default {
directives: {
highlight: {
mounted(el) {
el.style.backgroundColor = 'yellow'
}
}
}
}
2. 插件开发
// myPlugin.js
export default {
install(app, options) {
// 添加全局方法或属性
app.config.globalProperties.$myMethod = () => {
console.log('这是插件添加的方法')
}
// 添加全局指令
app.directive('my-directive', {
mounted(el, binding) {
// 指令逻辑
}
})
}
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import myPlugin from './myPlugin'
const app = createApp(App)
app.use(myPlugin, { someOption: true })
app.mount('#app')
3. 使用 TypeScript
// 定义 Props 类型
interface Props {
msg: string
count?: number
}
export default defineComponent({
props: {
msg: {
type: String as PropType<string>,
required: true
},
count: {
type: Number as PropType<number>,
default: 0
}
},
setup(props: Props) {
const state = reactive({
name: 'Vue 3'
})
return {
state
}
}
})
4. 状态管理 (Pinia)
Pinia 是 Vue 3 推荐的状态管理库。
npm install pinia
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++
}
},
getters: {
doubleCount: (state) => state.count * 2
}
})
// 组件中使用
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
return {
counter
}
}
}
六、路由 (Vue Router)
npm install vue-router@4
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
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')
// 组件中使用
import { useRouter, useRoute } from 'vue-router'
export default {
setup() {
const router = useRouter()
const route = useRoute()
const goToAbout = () => {
router.push('/about')
}
return {
goToAbout,
currentPath: computed(() => route.path)
}
}
}
七、实战示例
1. Todo List 应用
运行
<template>
<div>
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="添加新任务"
>
<ul>
<li v-for="(todo, index) in todos" :key="index">
<input type="checkbox" v-model="todo.completed">
<span :class="{ completed: todo.completed }">{{ todo.text }}</span>
<button @click="removeTodo(index)">删除</button>
</li>
</ul>
<p>剩余任务: {{ remaining }} / {{ todos.length }}</p>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const newTodo = ref('')
const todos = ref([
{ text: '学习 Vue 3', completed: false },
{ text: '完成项目', completed: false }
])
const remaining = computed(() => {
return todos.value.filter(todo => !todo.completed).length
})
function addTodo() {
if (newTodo.value.trim()) {
todos.value.push({
text: newTodo.value,
completed: false
})
newTodo.value = ''
}
}
function removeTodo(index) {
todos.value.splice(index, 1)
}
return {
newTodo,
todos,
remaining,
addTodo,
removeTodo
}
}
}
</script>
<style>
.completed {
text-decoration: line-through;
color: #999;
}
</style>
八、最佳实践
- 组件设计
- 单一职责原则
- 合理拆分组件
- 使用有意义的组件名
- 代码组织
- 使用组合式 API 提取可复用逻辑
- 合理使用自定义 hooks
- 保持 setup 函数简洁
- 性能优化
- 使用 v-once 和 v-memo 进行静态内容优化
- 合理使用 computed 和 watch
- 大型列表使用虚拟滚动
- 测试
- 单元测试 (Vitest/Jest)
- 组件测试 (Vue Test Utils)
- E2E 测试 (Cypress)
九、学习资源
- Vue 3 官方文档
- Vue Mastery
- Vue School
- Vue.js 中文社区
希望这份详细教程能帮助你掌握 Vue 3!从基础到进阶,Vue 3 提供了强大的功能和灵活的编程模式,适合构建各种规模的应用程序。