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 = newValuetouched.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 | nullerror: Error | nullstatus: '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 Errorstate.status = 'error'}}return { state, execute }
}// 使用示例
const { state, execute } = useAsyncTask(fetchUserList)
3.2 响应式存储模式
class ReactiveStore<T extends object> {private state: Tprivate proxy: Tconstructor(initialState: T) {this.state = initialStatethis.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: numbertotalItems: 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: booleantitle?: stringtransition?: '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: numberpageSize: numberfetcher: (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().permissionsif (!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)}
})