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