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