perf(reactivity): trigger deps directly instead of storing in an array first (#11695)

This commit is contained in:
zhangenming 2024-09-10 15:48:51 +08:00 committed by GitHub
parent ced59ab8f2
commit f80d447c17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 29 additions and 28 deletions

View File

@ -250,11 +250,29 @@ export function trigger(
return
}
let deps: Dep[] = []
const run = (dep: Dep | undefined) => {
if (dep) {
if (__DEV__) {
dep.trigger({
target,
type,
key,
newValue,
oldValue,
oldTarget,
})
} else {
dep.trigger()
}
}
}
startBatch()
if (type === TriggerOpTypes.CLEAR) {
// collection being cleared
// trigger all effects for target
deps = [...depsMap.values()]
depsMap.forEach(run)
} else {
const targetIsArray = isArray(target)
const isArrayIndex = targetIsArray && isIntegerKey(key)
@ -267,67 +285,50 @@ export function trigger(
key === ARRAY_ITERATE_KEY ||
(!isSymbol(key) && key >= newLength)
) {
deps.push(dep)
run(dep)
}
})
} else {
const push = (dep: Dep | undefined) => dep && deps.push(dep)
// schedule runs for SET | ADD | DELETE
if (key !== void 0) {
push(depsMap.get(key))
run(depsMap.get(key))
}
// schedule ARRAY_ITERATE for any numeric key change (length is handled above)
if (isArrayIndex) {
push(depsMap.get(ARRAY_ITERATE_KEY))
run(depsMap.get(ARRAY_ITERATE_KEY))
}
// also run for iteration key on ADD | DELETE | Map.SET
switch (type) {
case TriggerOpTypes.ADD:
if (!targetIsArray) {
push(depsMap.get(ITERATE_KEY))
run(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
push(depsMap.get(MAP_KEY_ITERATE_KEY))
run(depsMap.get(MAP_KEY_ITERATE_KEY))
}
} else if (isArrayIndex) {
// new index added to array -> length changes
push(depsMap.get('length'))
run(depsMap.get('length'))
}
break
case TriggerOpTypes.DELETE:
if (!targetIsArray) {
push(depsMap.get(ITERATE_KEY))
run(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
push(depsMap.get(MAP_KEY_ITERATE_KEY))
run(depsMap.get(MAP_KEY_ITERATE_KEY))
}
}
break
case TriggerOpTypes.SET:
if (isMap(target)) {
push(depsMap.get(ITERATE_KEY))
run(depsMap.get(ITERATE_KEY))
}
break
}
}
}
startBatch()
for (const dep of deps) {
if (__DEV__) {
dep.trigger({
target,
type,
key,
newValue,
oldValue,
oldTarget,
})
} else {
dep.trigger()
}
}
endBatch()
}