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 { isFunction, NOOP } from '@vue/shared'
@ -42,16 +43,20 @@ export function computed<T>(
let dirty = true
let value: T
let computed: ComputedRef<T>
const runner = effect(getter, {
lazy: true,
// mark effect as computed so that it gets priority during trigger
computed: true,
scheduler: () => {
if (!dirty) {
dirty = true
trigger(computed, TriggerOpTypes.SET, 'value')
}
}
})
return {
computed = {
_isRef: true,
// expose effect so computed can be stopped
effect: runner,
@ -60,27 +65,12 @@ export function computed<T>(
value = runner()
dirty = false
}
// When computed effects are accessed in a parent effect, the parent
// should track all the dependencies the computed property has tracked.
// This should also apply for chained computed properties.
trackChildRun(runner)
track(computed, TrackOpTypes.GET, 'value')
return value
},
set value(newValue: T) {
setter(newValue)
}
} as any
}
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)
}
}
return computed
}