建立公司网站步骤百度快照首页
Vue 3 的双向绑定原理主要基于 Proxy
和 Reflect
,核心源码在 reactivity
模块中。
1. 核心模块:reactivity
reactivity
模块负责响应式数据的实现,主要包括以下几个文件:
reactive.ts
:处理对象和数组的响应式。ref.ts
:处理基本类型的响应式。effect.ts
:管理副作用和依赖追踪。
2. reactive.ts
reactive.ts
中的 reactive
函数将普通对象转换为响应式对象,核心代码如下:
export function reactive<T extends object>(target: T): T {if (target && (target as any).__v_isReadonly) {return target}return createReactiveObject(target,false,mutableHandlers,mutableCollectionHandlers)
}function createReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>
) {if (!isObject(target)) {return target}const proxy = new Proxy(target, baseHandlers)return proxy
}
reactive
函数通过 Proxy
包装目标对象,mutableHandlers
定义了 get
和 set
等拦截操作。
3. mutableHandlers
mutableHandlers
定义了 Proxy
的拦截行为,核心代码如下:
export const mutableHandlers: ProxyHandler<object> = {get(target: Target, key: string | symbol, receiver: object) {const res = Reflect.get(target, key, receiver)track(target, key)return isObject(res) ? reactive(res) : res},set(target: Target, key: string | symbol, value: any, receiver: object) {const oldValue = (target as any)[key]const result = Reflect.set(target, key, value, receiver)if (hasChanged(value, oldValue)) {trigger(target, key)}return result}
}
get
:在访问属性时调用track
追踪依赖。set
:在修改属性时调用trigger
触发更新。
4. effect.ts
effect.ts
负责管理副作用和依赖追踪,核心代码如下:
export function effect<T = any>(fn: () => T,options: ReactiveEffectOptions = EMPTY_OBJ
): ReactiveEffect<T> {const effect = createReactiveEffect(fn, options)if (!options.lazy) {effect()}return effect
}function createReactiveEffect<T = any>(fn: () => T,options: ReactiveEffectOptions
): ReactiveEffect<T> {const effect = function reactiveEffect(): unknown {if (!effect.active) {return options.scheduler ? undefined : fn()}if (!effectStack.includes(effect)) {cleanup(effect)try {enableTracking()effectStack.push(effect)activeEffect = effectreturn fn()} finally {effectStack.pop()resetTracking()activeEffect = effectStack[effectStack.length - 1]}}} as ReactiveEffecteffect.id = uid++effect._isEffect = trueeffect.active = trueeffect.raw = fneffect.deps = []effect.options = optionsreturn effect
}
effect
函数创建并执行副作用函数,track
和 trigger
分别用于依赖追踪和触发更新。
5. track
和 trigger
track
和 trigger
是依赖追踪和更新的核心:
export function track(target: object, key: unknown) {if (!shouldTrack || activeEffect === undefined) {return}let depsMap = targetMap.get(target)if (!depsMap) {targetMap.set(target, (depsMap = new Map()))}let dep = depsMap.get(key)if (!dep) {depsMap.set(key, (dep = new Set()))}if (!dep.has(activeEffect)) {dep.add(activeEffect)activeEffect.deps.push(dep)}
}export function trigger(target: object,key?: unknown,newValue?: unknown,oldValue?: unknown,oldTarget?: Map<unknown, unknown> | Set<unknown>
) {const depsMap = targetMap.get(target)if (!depsMap) {return}const effects = new Set<ReactiveEffect>()const add = (effectsToAdd: Set<ReactiveEffect> | undefined) => {if (effectsToAdd) {effectsToAdd.forEach(effect => {if (effect !== activeEffect || effect.allowRecurse) {effects.add(effect)}})}}if (key !== void 0) {add(depsMap.get(key))}const run = (effect: ReactiveEffect) => {if (effect.options.scheduler) {effect.options.scheduler(effect)} else {effect()}}effects.forEach(run)
}
track
:将当前副作用函数添加到依赖集合。trigger
:遍历依赖集合并执行副作用函数。
Vue 3 的双向绑定通过 Proxy
拦截对象操作,结合 track
和 trigger
实现依赖追踪和更新触发。effect
函数管理副作用,确保数据变化时视图自动更新。