主题
Composition API
1. 基础概念
1.1 什么是Composition API
Composition API是Vue3中新增的一种组织组件逻辑的方式,它允许我们按照功能逻辑来组织代码,而不是像Options API那样按照选项类型组织。
1.2 为什么需要Composition API
- 更好的代码组织
- 更好的逻辑复用
- 更好的类型推导
- 更小的打包体积
2. 核心API
2.1 setup函数
js
import { ref, onMounted } from 'vue'
export default {
setup(props, context) {
// 响应式数据
const count = ref(0)
// 生命周期钩子
onMounted(() => {
console.log('组件已挂载')
})
// 返回给模板使用
return {
count
}
}
}
2.2 响应式API
ref和reactive
js
import { ref, reactive } from 'vue'
// ref用于基础类型
const count = ref(0)
console.log(count.value) // 访问值需要.value
// reactive用于对象类型
const state = reactive({
user: {
name: 'John',
age: 20
}
})
console.log(state.user.name) // 直接访问
computed和watch
js
import { ref, computed, watch, watchEffect } from 'vue'
// 计算属性
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
// 监听器
watch(count, (newValue, oldValue) => {
console.log('count changed:', newValue, oldValue)
})
// 副作用监听
watchEffect(() => {
console.log('count is:', count.value)
})
3. 生命周期钩子
3.1 组合式API中的生命周期
js
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
export default {
setup() {
onBeforeMount(() => {
// 组件挂载前
})
onMounted(() => {
// 组件挂载后
})
onBeforeUpdate(() => {
// 组件更新前
})
onUpdated(() => {
// 组件更新后
})
onBeforeUnmount(() => {
// 组件卸载前
})
onUnmounted(() => {
// 组件卸载后
})
}
}
4. 组合式函数(Composables)
4.1 创建可复用的组合式函数
js
// useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
doubleCount,
increment,
decrement
}
}
// 在组件中使用
import { useCounter } from './composables/useCounter'
export default {
setup() {
const { count, doubleCount, increment } = useCounter(10)
return { count, doubleCount, increment }
}
}
4.2 异步组合式函数
js
// useFetch.js
import { ref } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(true)
fetch(url)
.then(res => res.json())
.then(json => data.value = json)
.catch(err => error.value = err)
.finally(() => loading.value = false)
return { data, error, loading }
}
5. 与TypeScript集成
5.1 类型定义
ts
import { ref, defineComponent } from 'vue'
interface User {
name: string
age: number
}
export default defineComponent({
setup() {
const user = ref<User>({
name: 'John',
age: 20
})
return { user }
}
})
5.2 Props类型
ts
import { defineComponent, PropType } from 'vue'
interface Props {
message: string
user: User
}
export default defineComponent({
props: {
message: String,
user: Object as PropType<User>
},
setup(props: Props) {
// 使用props
}
})
6. 最佳实践
6.1 代码组织
js
// 按功能拆分组合式函数
function useUser() {
const user = ref(null)
const loading = ref(false)
async function fetchUser(id) {
loading.value = true
user.value = await api.getUser(id)
loading.value = false
}
return {
user,
loading,
fetchUser
}
}
// 在组件中组合使用
export default {
setup() {
const { user, fetchUser } = useUser()
const { posts } = usePosts()
return {
user,
fetchUser,
posts
}
}
}
6.2 性能优化
- 合理使用
shallowRef
和shallowReactive
- 使用
computed
缓存计算结果 - 避免不必要的响应式
- 及时清理副作用
6.3 调试技巧
- 使用Vue Devtools
- 合理命名ref和reactive变量
- 使用开发环境警告
- 性能追踪
7. 注意事项
- setup函数中没有this
- 避免直接解构props
- 响应式数据的局限性
- 生命周期钩子的使用时机