perf(reactivity): better computed tracking (#710)

This commit is contained in:
jods 2020-02-09 21:25:17 +01:00 committed by GitHub
parent fc7bcca1b3
commit 8874b21a7e

View File

@ -1,4 +1,5 @@
import { effect, ReactiveEffect, activeEffect } from './effect' import { effect, ReactiveEffect, trigger, track } from './effect'
import { TriggerOpTypes, TrackOpTypes } from './operations'
import { Ref, UnwrapRef } from './ref' import { Ref, UnwrapRef } from './ref'
import { isFunction, NOOP } from '@vue/shared' import { isFunction, NOOP } from '@vue/shared'
@ -42,16 +43,20 @@ export function computed<T>(
let dirty = true let dirty = true
let value: T let value: T
let computed: ComputedRef<T>
const runner = effect(getter, { const runner = effect(getter, {
lazy: true, lazy: true,
// mark effect as computed so that it gets priority during trigger // mark effect as computed so that it gets priority during trigger
computed: true, computed: true,
scheduler: () => { scheduler: () => {
dirty = true if (!dirty) {
dirty = true
trigger(computed, TriggerOpTypes.SET, 'value')
}
} }
}) })
return { computed = {
_isRef: true, _isRef: true,
// expose effect so computed can be stopped // expose effect so computed can be stopped
effect: runner, effect: runner,
@ -60,27 +65,12 @@ export function computed<T>(
value = runner() value = runner()
dirty = false dirty = false
} }
// When computed effects are accessed in a parent effect, the parent track(computed, TrackOpTypes.GET, 'value')
// should track all the dependencies the computed property has tracked.
// This should also apply for chained computed properties.
trackChildRun(runner)
return value return value
}, },
set value(newValue: T) { set value(newValue: T) {
setter(newValue) setter(newValue)
} }
} as any } as any
} return computed
function trackChildRun(childRunner: ReactiveEffect) {
if (activeEffect === undefined) {
return
}
for (let i = 0; i < childRunner.deps.length; i++) {
const dep = childRunner.deps[i]
if (!dep.has(activeEffect)) {
dep.add(activeEffect)
activeEffect.deps.push(dep)
}
}
} }