Vue3 Composition API 深度开发指南
Vue3 Composition API 深度开发指南
响应式系统核心解析
1.1 响应式原理解构
Vue3 基于 Proxy 实现响应式追踪,其核心流程为:
const reactiveHandler = {
get(target, key, receiver) {
track(target, key) // 依赖收集
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
trigger(target, key) // 触发更新
return result
}
}
function reactive(obj) {
return new Proxy(obj, reactiveHandler)
}
关键差异:
ref
通过对象包装实现基础类型响应式reactive
直接代理整个对象shallowRef/shallowReactive
实现浅层响应
1.2 响应式工具进阶
// 响应式转换控制
const readonlyUser = readonly(reactive({ name: 'Alice' }))
// 解构保持响应性
const { x, y } = toRefs(reactiveMousePosition)
// Ref类型自动解包
const count = ref(0)
const double = computed(() => count.value * 2)
组件设计模式深度实践
2.1 受控组件模式
// 通用表单控制逻辑
export function useFormControl<T>(initialValue: T) {
const value = ref<T>(initialValue)
const touched = ref(false)
const setValue = (newValue: T) => {
value.value = newValue
touched.value = true
}
return {
value: readonly(value),
isTouched: readonly(touched),
setValue
}
}
// 组件实现
const emailControl = useFormControl<string>('')
2.2 依赖注入模式
// 上下文类型定义
interface EditorContext {
content: Ref<string>
formatters: Map<string, FormatterFn>
}
// 提供者组件
const editorSymbol = Symbol() as InjectionKey<EditorContext>
provide(editorSymbol, {
content: ref(''),
formatters: new Map([['bold', text => `**${text}**`]])
})
// 消费者组件
const { formatters } = inject(editorSymbol)!
Composition API 高级模式
3.1 异步状态机
type AsyncState<T> = {
data: T | null
error: Error | null
status: 'idle' | 'pending' | 'success' | 'error'
}
export function useAsyncTask<T>(task: () => Promise<T>) {
const state = reactive<AsyncState<T>>({
data: null,
error: null,
status: 'idle'
})
const execute = async () => {
state.status = 'pending'
try {
state.data = await task()
state.status = 'success'
} catch (err) {
state.error = err as Error
state.status = 'error'
}
}
return { state, execute }
}
// 使用示例
const { state, execute } = useAsyncTask(fetchUserList)
3.2 响应式存储模式
class ReactiveStore<T extends object> {
private state: T
private proxy: T
constructor(initialState: T) {
this.state = initialState
this.proxy = reactive(initialState) as T
}
getState(): Readonly<T> {
return readonly(this.proxy)
}
mutate(mutation: (state: T) => void) {
mutation(this.proxy)
}
}
// 创建Store实例
const userStore = new ReactiveStore({
id: 0,
profile: { name: '' }
})
// 组件中使用
const { id } = userStore.getState()
性能优化策略
4.1 计算属性缓存策略
const heavyList = ref<Item[]>(/* 大数据集 */)
// 带缓存的筛选计算
const filteredList = computed(() => {
return heavyList.value.filter(item =>
item.category === 'active' &&
item.value > 1000
)
})
// 计算属性调试
const debugComputed = computed({
get() { /* 原逻辑 */ },
set() { /* 开发环境调试钩子 */ }
})
4.2 虚拟滚动优化
// 虚拟滚动Composable
export function useVirtualScroll(options: {
containerRef: Ref<HTMLElement | null>
itemHeight: number
totalItems: number
}) {
const scrollTop = ref(0)
const visibleCount = computed(() =>
Math.ceil(options.containerRef.value!.clientHeight / options.itemHeight)
)
const startIndex = computed(() =>
Math.floor(scrollTop.value / options.itemHeight)
)
const endIndex = computed(() =>
Math.min(startIndex.value + visibleCount.value + 2, options.totalItems)
)
return { scrollTop, startIndex, endIndex }
}
类型系统深度集成
5.1 复杂类型推导
// 类型安全的provide/inject
const LOCALE_KEY = Symbol() as InjectionKey<{
lang: Ref<string>
setLang: (lang: string) => void
}>
// Props类型增强
interface ModalProps {
modelValue: boolean
title?: string
transition?: 'fade' | 'slide'
}
const props = defineProps<ModalProps>()
// Emits类型约束
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void
(e: 'confirm', payload: { timestamp: number }): void
}>()
5.2 泛型Composable
interface PaginationOptions<T> {
initialPage: number
pageSize: number
fetcher: (page: number) => Promise<T[]>
}
export function usePagination<T>(options: PaginationOptions<T>) {
const currentPage = ref(options.initialPage)
const list = ref<T[]>([]) as Ref<T[]>
const loadPage = async () => {
list.value = await options.fetcher(currentPage.value)
}
return {
currentPage,
list,
loadPage
}
}
// 使用示例
const { list, loadPage } = usePagination<User>({
initialPage: 1,
pageSize: 20,
fetcher: fetchUsers
})
工程化实践
6.1 自定义指令开发
// 权限控制指令
const vPermission = {
mounted(el: HTMLElement, binding: DirectiveBinding<string[]>) {
const userPermissions = useAuthStore().permissions
if (!binding.value.some(perm => userPermissions.includes(perm))) {
el.parentNode?.removeChild(el)
}
}
}
// 使用方式
<button v-permission="['admin', 'editor']">删除</button>
6.2 单元测试策略
// 测试Composable
import { useCounter } from './counter'
import { renderHook } from '@testing-library/vue'
test('counter logic', async () => {
const { result } = renderHook(() => useCounter(10))
expect(result.current.count.value).toBe(10)
await result.current.increment()
expect(result.current.count.value).toBe(11)
await result.current.reset()
expect(result.current.count.value).toBe(10)
})
响应式调试技巧
7.1 依赖追踪可视化
// 调试watch效果
const stop = watchEffect((onCleanup) => {
console.log('依赖变化:', effectScope.activeEffect?.deps)
onCleanup(() => {
console.log('清理副作用')
})
})
// Chrome DevTools + Vue DevTools 组合调试
7.2 响应式树分析
import { DebuggerEvent, debug } from 'vue'
debug({
onTrack(e: DebuggerEvent) {
if (e.target === store) {
console.log('Store被追踪:', e)
}
},
onTrigger(e: DebuggerEvent) {
console.log('响应式触发:', e)
}
})