Vue 3全面指南:从入门到精通
目录
- 基础概念与环境搭建
- 组合式API (Composition API)
- 响应式系统
- 组件开发
- 高级特性
- 性能优化
- 最佳实践
1. 基础概念与环境搭建
1.1 创建Vue 3项目
# 使用 Vite 创建项目
npm create vite@latest my-vue-app -- --template vue
# 使用 Vue CLI 创建项目
npm init vue@latest
1.2 项目结构
my-vue-app/
├── public/
├── src/
│ ├── assets/
│ ├── components/
│ ├── views/
│ ├── App.vue
│ └── main.js
├── package.json
└── vite.config.js
2. 组合式API (Composition API)
2.1 基础示例
<template>
<div class="user-profile">
<h1>{
{ userState.name }}的个人信息</h1>
<div class="info">
<p>年龄:{
{ userState.age }}</p>
<p>邮箱:{
{ userState.email }}</p>
</div>
<button @click="updateAge">年龄+1</button>
</div>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
// 状态定义
const userState = reactive({
name: '张三',
age: 25,
email: '[email protected]'
})
// 方法定义
const updateAge = () => {
userState.age++
}
// 生命周期钩子
onMounted(() => {
console.log('组件已挂载')
})
</script>
<style scoped>
.user-profile {
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
}
.info {
margin: 20px 0;
}
</style>
2.2 响应式系统
<template>
<div class="counter">
<h2>计数器示例</h2>
<p>当前计数:{
{ count }}</p>
<p>双倍值:{
{ doubleCount }}</p>
<button @click="increment">增加</button>
<button @click="reset">重置</button>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
// ref 响应式引用
const count = ref(0)
// computed 计算属性
const doubleCount = computed(() => count.value * 2)
// 方法
const increment = () => {
count.value++
}
const reset = () => {
count.value = 0
}
// watch 侦听器
watch(count, (newValue, oldValue) => {
console.log(`计数从 ${oldValue} 变为 ${newValue}`)
})
</script>
2.3 生命周期钩子
<script setup>
import { onMounted, onUpdated, onUnmounted, onBeforeMount } from 'vue'
onBeforeMount(() => {
console.log('组件挂载前')
})
onMounted(() => {
console.log('组件已挂载')
})
onUpdated(() => {
console.log('组件已更新')
})
onUnmounted(() => {
console.log('组件已卸载')
})
</script>
3. 响应式系统
3.1 ref vs reactive
<script setup>
import { ref, reactive } from 'vue'
// ref 用于基本类型
const count = ref(0)
const message = ref('Hello')
// reactive 用于对象
const state = reactive({
user: {
name: '张三',
age: 25
},
settings: {
theme: 'dark'
}
})
// 访问和修改
console.log(count.value) // 需要.value
console.log(state.user.name) // 直接访问
const updateState = () => {
count.value++
state.user.age++
}
</script>
3.2 计算属性和侦听器
<script setup>
import { ref, computed, watch, watchEffect } from 'vue'
const count = ref(0)
const message = ref('Hello')
// 计算属性
const doubleCount = computed(() => count.value * 2)
const reversedMessage = computed(() => message.value.split('').reverse().join(''))
// 侦听器
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`)
})
// watchEffect
watchEffect(() => {
console.log(`count is: ${count.value}`)
console.log(`message is: ${message.value}`)
})
</script>
````markdown
## 4. 组件开发
### 4.1 Props定义
````vue
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
},
user: {
type: Object,
default: () => ({
name: '默认用户',
age: 20
})
}
})
</script>
4.2 事件发射
<template>
<div>
<button @click="handleClick">点击发射事件</button>
</div>
</template>
<script setup>
import { defineEmits } from 'vue'
const emit = defineEmits(['update', 'delete'])
const handleClick = () => {
emit('update', { id: 1, data: 'new data' })
}
</script>
4.3 插槽使用
<template>
<div class="card">
<header>
<slot name="header">默认标题</slot>
</header>
<main>
<slot>默认内容</slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
5. 高级特性
5.1 Teleport组件
<template>
<button @click="showModal = true">打开模态框</button>
<teleport to="body">
<div v-if="showModal" class="modal">
<h3>模态框标题</h3>
<p>这是一个传送门示例</p>
<button @click="showModal = false">关闭</button>
</div>
</teleport>
</template>
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
</script>
<style scoped>
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
</style>
5.2 Suspense异步组件
<template>
<Suspense>
<template #default>
<async-component />
</template>
<template #fallback>
<div class="loading">加载中...</div>
</template>
</Suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
)
</script>
5.3 自定义指令
<script setup>
// v-focus 指令
const vFocus = {
mounted: (el) => el.focus()
}
// v-click-outside 指令
const vClickOutside = {
mounted: (el, binding) => {
el._clickOutside = (event) => {
if (!(el === event.target || el.contains(event.target))) {
binding.value(event)
}
}
document.addEventListener('click', el._clickOutside)
},
unmounted: (el) => {
document.removeEventListener('click', el._clickOutside)
}
}
</script>
6. 性能优化
6.1 动态组件优化
<template>
<component
:is="currentComponent"
v-bind="componentProps"
/>
</template>
<script setup>
import { shallowRef, markRaw } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
// 使用 shallowRef 和 markRaw 优化动态组件
const components = {
a: markRaw(ComponentA),
b: markRaw(ComponentB)
}
const currentComponent = shallowRef(components.a)
</script>
6.2 大列表优化
<template>
<div class="virtual-list">
<div
class="list-container"
:style="{ height: totalHeight + 'px' }"
>
<div
v-for="item in visibleItems"
:key="item.id"
:style="{
position: 'absolute',
top: item.top + 'px'
}"
>
{
{ item.content }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const itemHeight = 50
const visibleCount = Math.ceil(window.innerHeight / itemHeight)
const startIndex = ref(0)
const items = Array.from({ length: 10000 }, (_, i) => ({
id: i,
content: `Item ${i}`,
}))
const visibleItems = computed(() => {
return items
.slice(startIndex.value, startIndex.value + visibleCount)
.map((item, index) => ({
...item,
top: (startIndex.value + index) * itemHeight
}))
})
const totalHeight = items.length * itemHeight
</script>
7. 最佳实践
7.1 组合式函数封装
// useApi.js
import { ref } from 'vue'
export function useApi(apiFunc) {
const data = ref(null)
const loading = ref(false)
const error = ref(null)
const execute = async (...args) => {
loading.value = true
error.value = null
try {
data.value = await apiFunc(...args)
} catch (e) {
error.value = e
} finally {
loading.value = false
}
}
return {
data,
loading,
error,
execute
}
}
// 使用示例
const { data, loading, error, execute } = useApi(fetchUserData)
7.2 状态管理
// store/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
user: null,
token: null
}),
getters: {
isLoggedIn: (state) => !!state.token
},
actions: {
async login(credentials) {
const { token, user } = await api.login(credentials)
this.token = token
this.user = user
},
logout() {
this.token = null
this.user = null
}
}
})
总结
Vue 3提供了强大的功能和优秀的性能:
-
响应式系统
- 基于Proxy的响应式
- 更好的性能
- 更完善的类型支持
-
组合式API
- 更好的代码组织
- 更强的代码复用
- 更清晰的逻辑分离
-
性能优化
- 更小的打包体积
- 更快的渲染速度
- 更好的内存使用
-
开发体验
- 更好的TypeScript支持
- 更强大的开发工具
- 更完善的生态系统
参考资料
本文详细介绍了Vue 3的核心特性和最佳实践,希望能帮助开发者更好地理解和使用Vue 3。如有问题,欢迎在评论区讨论。