refactor(reactivity): refactor iteration key trigger logic + use more robust Map/Set check

This commit is contained in:
Evan You
2020-09-14 11:26:34 -04:00
parent cf1b6c666f
commit 0124eacc91
5 changed files with 48 additions and 28 deletions

View File

@@ -6,7 +6,8 @@ import {
capitalize,
hasOwn,
hasChanged,
toRawType
toRawType,
isMap
} from '@vue/shared'
export type CollectionTypes = IterableCollections | WeakCollections
@@ -129,7 +130,7 @@ function clear(this: IterableCollections) {
const target = toRaw(this)
const hadItems = target.size !== 0
const oldTarget = __DEV__
? target instanceof Map
? isMap(target)
? new Map(target)
: new Set(target)
: undefined
@@ -185,9 +186,10 @@ function createIterableMethod(
): Iterable & Iterator {
const target = (this as any)[ReactiveFlags.RAW]
const rawTarget = toRaw(target)
const isMap = rawTarget instanceof Map
const isPair = method === 'entries' || (method === Symbol.iterator && isMap)
const isKeyOnly = method === 'keys' && isMap
const targetIsMap = isMap(rawTarget)
const isPair =
method === 'entries' || (method === Symbol.iterator && targetIsMap)
const isKeyOnly = method === 'keys' && targetIsMap
const innerIterator = target[method](...args)
const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive
!isReadonly &&

View File

@@ -1,5 +1,5 @@
import { TrackOpTypes, TriggerOpTypes } from './operations'
import { EMPTY_OBJ, isArray, isIntegerKey } from '@vue/shared'
import { EMPTY_OBJ, 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
@@ -197,19 +197,33 @@ export function trigger(
if (key !== void 0) {
add(depsMap.get(key))
}
// also run for iteration key on ADD | DELETE | Map.SET
const shouldTriggerIteration =
(type === TriggerOpTypes.ADD &&
(!isArray(target) || isIntegerKey(key))) ||
(type === TriggerOpTypes.DELETE && !isArray(target))
if (
shouldTriggerIteration ||
(type === TriggerOpTypes.SET && target instanceof Map)
) {
add(depsMap.get(isArray(target) ? 'length' : ITERATE_KEY))
}
if (shouldTriggerIteration && target instanceof Map) {
add(depsMap.get(MAP_KEY_ITERATE_KEY))
switch (type) {
case TriggerOpTypes.ADD:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY))
}
} else if (isIntegerKey(key)) {
// new index added to array -> length changes
add(depsMap.get('length'))
}
break
case TriggerOpTypes.DELETE:
if (!isArray(target)) {
add(depsMap.get(ITERATE_KEY))
if (isMap(target)) {
add(depsMap.get(MAP_KEY_ITERATE_KEY))
}
}
break
case TriggerOpTypes.SET:
if (isMap(target)) {
add(depsMap.get(ITERATE_KEY))
}
break
}
}