forked from vuejs/core
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move code to reactiveEffect.ts
- Loading branch information
1 parent
93b5beb
commit fc76e81
Showing
7 changed files
with
160 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import { isArray, isIntegerKey, isMap } from '@vue/shared' | ||
import { DirtyLevels, TrackOpTypes, TriggerOpTypes } from './constants' | ||
import { createDep, Dep } from './dep' | ||
import { | ||
activeEffect, | ||
pauseScheduling, | ||
resetScheduling, | ||
shouldTrack, | ||
trackEffect, | ||
triggerEffects | ||
} from './effect' | ||
|
||
// The main WeakMap that stores {target -> key -> dep} connections. | ||
// Conceptually, it's easier to think of a dependency as a Dep class | ||
// which maintains a Set of subscribers, but we simply store them as | ||
// raw Sets to reduce memory overhead. | ||
type KeyToDepMap = Map<any, Dep> | ||
const targetMap = new WeakMap<object, KeyToDepMap>() | ||
|
||
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '') | ||
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '') | ||
|
||
/** | ||
* Tracks access to a reactive property. | ||
* | ||
* This will check which effect is running at the moment and record it as dep | ||
* which records all effects that depend on the reactive property. | ||
* | ||
* @param target - Object holding the reactive property. | ||
* @param type - Defines the type of access to the reactive property. | ||
* @param key - Identifier of the reactive property to track. | ||
*/ | ||
export function track(target: object, type: TrackOpTypes, key: unknown) { | ||
if (shouldTrack && activeEffect) { | ||
let depsMap = targetMap.get(target) | ||
if (!depsMap) { | ||
targetMap.set(target, (depsMap = new Map())) | ||
} | ||
let dep = depsMap.get(key) | ||
if (!dep) { | ||
depsMap.set(key, (dep = createDep(() => depsMap!.delete(key)))) | ||
} | ||
if (__DEV__) { | ||
trackEffect(activeEffect, dep, { | ||
target, | ||
type, | ||
key | ||
}) | ||
} else { | ||
trackEffect(activeEffect, dep) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Finds all deps associated with the target (or a specific property) and | ||
* triggers the effects stored within. | ||
* | ||
* @param target - The reactive object. | ||
* @param type - Defines the type of the operation that needs to trigger effects. | ||
* @param key - Can be used to target a specific reactive property in the target object. | ||
*/ | ||
export function trigger( | ||
target: object, | ||
type: TriggerOpTypes, | ||
key?: unknown, | ||
newValue?: unknown, | ||
oldValue?: unknown, | ||
oldTarget?: Map<unknown, unknown> | Set<unknown> | ||
) { | ||
const depsMap = targetMap.get(target) | ||
if (!depsMap) { | ||
// never been tracked | ||
return | ||
} | ||
|
||
let deps: (Dep | undefined)[] = [] | ||
if (type === TriggerOpTypes.CLEAR) { | ||
// collection being cleared | ||
// trigger all effects for target | ||
deps = [...depsMap.values()] | ||
} else if (key === 'length' && isArray(target)) { | ||
const newLength = Number(newValue) | ||
depsMap.forEach((dep, key) => { | ||
if (key === 'length' || key >= newLength) { | ||
deps.push(dep) | ||
} | ||
}) | ||
} else { | ||
// schedule runs for SET | ADD | DELETE | ||
if (key !== void 0) { | ||
deps.push(depsMap.get(key)) | ||
} | ||
|
||
// also run for iteration key on ADD | DELETE | Map.SET | ||
switch (type) { | ||
case TriggerOpTypes.ADD: | ||
if (!isArray(target)) { | ||
deps.push(depsMap.get(ITERATE_KEY)) | ||
if (isMap(target)) { | ||
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) | ||
} | ||
} else if (isIntegerKey(key)) { | ||
// new index added to array -> length changes | ||
deps.push(depsMap.get('length')) | ||
} | ||
break | ||
case TriggerOpTypes.DELETE: | ||
if (!isArray(target)) { | ||
deps.push(depsMap.get(ITERATE_KEY)) | ||
if (isMap(target)) { | ||
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)) | ||
} | ||
} | ||
break | ||
case TriggerOpTypes.SET: | ||
if (isMap(target)) { | ||
deps.push(depsMap.get(ITERATE_KEY)) | ||
} | ||
break | ||
} | ||
} | ||
|
||
pauseScheduling() | ||
for (const dep of deps) { | ||
if (dep) { | ||
if (__DEV__) { | ||
triggerEffects(dep, DirtyLevels.Dirty, { | ||
target, | ||
type, | ||
key, | ||
newValue, | ||
oldValue, | ||
oldTarget | ||
}) | ||
} else { | ||
triggerEffects(dep, DirtyLevels.Dirty) | ||
} | ||
} | ||
} | ||
resetScheduling() | ||
} | ||
|
||
export function getDepFromReactive(object: any, key: string | number | symbol) { | ||
return targetMap.get(object)?.get(key) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters