diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index ed29a267..df74769e 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -1,5 +1,5 @@ import { TrackOpTypes, TriggerOpTypes } from './operations' -import { EMPTY_OBJ, isArray, isIntegerKey, isMap } from '@vue/shared' +import { EMPTY_OBJ, extend, isArray, isIntegerKey, isMap } from '@vue/shared' // The main WeakMap that stores {target -> key -> dep} connections. // Conceptually, it's easier to think of a dependency as a Dep class @@ -212,47 +212,47 @@ export function trigger( return } - let sets: DepSets = [] + let deps: (Dep | undefined)[] = [] if (type === TriggerOpTypes.CLEAR) { // collection being cleared // trigger all effects for target - sets = [...depsMap.values()] + deps = [...depsMap.values()] } else if (key === 'length' && isArray(target)) { depsMap.forEach((dep, key) => { if (key === 'length' || key >= (newValue as number)) { - sets.push(dep) + deps.push(dep) } }) } else { // schedule runs for SET | ADD | DELETE if (key !== void 0) { - sets.push(depsMap.get(key)) + deps.push(depsMap.get(key)) } // also run for iteration key on ADD | DELETE | Map.SET switch (type) { case TriggerOpTypes.ADD: if (!isArray(target)) { - sets.push(depsMap.get(ITERATE_KEY)) + deps.push(depsMap.get(ITERATE_KEY)) if (isMap(target)) { - sets.push(depsMap.get(MAP_KEY_ITERATE_KEY)) + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) } } else if (isIntegerKey(key)) { // new index added to array -> length changes - sets.push(depsMap.get('length')) + deps.push(depsMap.get('length')) } break case TriggerOpTypes.DELETE: if (!isArray(target)) { - sets.push(depsMap.get(ITERATE_KEY)) + deps.push(depsMap.get(ITERATE_KEY)) if (isMap(target)) { - sets.push(depsMap.get(MAP_KEY_ITERATE_KEY)) + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) } } break case TriggerOpTypes.SET: if (isMap(target)) { - sets.push(depsMap.get(ITERATE_KEY)) + deps.push(depsMap.get(ITERATE_KEY)) } break } @@ -261,51 +261,37 @@ export function trigger( const eventInfo = __DEV__ ? { target, type, key, newValue, oldValue, oldTarget } : undefined - triggerMultiEffects(sets, eventInfo) -} -type DepSets = (Dep | undefined)[] - -export function triggerMultiEffects( - depSets: DepSets, - debuggerEventExtraInfo?: DebuggerEventExtraInfo -) { - if (depSets.length === 1) { - if (depSets[0]) { - triggerEffects(depSets[0], debuggerEventExtraInfo) + if (deps.length === 1) { + if (deps[0]) { + triggerEffects(deps[0], eventInfo) } } else { - const sets = depSets.filter(s => !!s) as Dep[] - triggerEffects(concatSets(sets), debuggerEventExtraInfo) + const effects: ReactiveEffect[] = [] + for (const dep of deps) { + if (dep) { + effects.push(...dep) + } + } + triggerEffects(new Set(effects), eventInfo) } } -function concatSets(sets: Set[]): Set { - const all = ([] as T[]).concat(...sets.map(s => [...s!])) - return new Set(all) -} - export function triggerEffects( dep: Dep, debuggerEventExtraInfo?: DebuggerEventExtraInfo ) { - const run = (effect: ReactiveEffect) => { - if (__DEV__ && effect.options.onTrigger) { - effect.options.onTrigger( - Object.assign({ effect }, debuggerEventExtraInfo) - ) - } - if (effect.options.scheduler) { - effect.options.scheduler(effect) - } else { - effect() + // spread into array for stabilization + for (const effect of [...dep]) { + if (effect !== activeEffect || effect.allowRecurse) { + if (__DEV__ && effect.options.onTrigger) { + effect.options.onTrigger(extend({ effect }, debuggerEventExtraInfo)) + } + if (effect.options.scheduler) { + effect.options.scheduler(effect) + } else { + effect() + } } } - - const immutableDeps = [...dep] - immutableDeps.forEach(effect => { - if (effect !== activeEffect || effect.allowRecurse) { - run(effect) - } - }) } diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 3d7e2388..b88fb8be 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -38,28 +38,34 @@ type RefBase = { export function trackRefValue(ref: RefBase) { if (isTracking()) { ref = toRaw(ref) - const eventInfo = __DEV__ - ? { target: ref, type: TrackOpTypes.GET, key: 'value' } - : undefined if (!ref.dep) { ref.dep = new Set() } - trackEffects(ref.dep, eventInfo) + if (__DEV__) { + trackEffects(ref.dep, { + target: ref, + type: TrackOpTypes.GET, + key: 'value' + }) + } else { + trackEffects(ref.dep) + } } } export function triggerRefValue(ref: RefBase, newVal?: any) { ref = toRaw(ref) if (ref.dep) { - const eventInfo = __DEV__ - ? { - target: ref, - type: TriggerOpTypes.SET, - key: 'value', - newValue: newVal - } - : undefined - triggerEffects(ref.dep, eventInfo) + if (__DEV__) { + triggerEffects(ref.dep, { + target: ref, + type: TriggerOpTypes.SET, + key: 'value', + newValue: newVal + }) + } else { + triggerEffects(ref.dep) + } } }