mirror of https://github.com/vuejs/core.git
fix(reactivity): should not recompute if computed does not track reactive data (#12341)
close #12337
This commit is contained in:
parent
8b848cbbd2
commit
0b23fd2383
|
@ -1012,6 +1012,17 @@ describe('reactivity/computed', () => {
|
||||||
expect(cValue.value).toBe(1)
|
expect(cValue.value).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should not recompute if computed does not track reactive data', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const c1 = computed(() => spy())
|
||||||
|
|
||||||
|
c1.value
|
||||||
|
ref(0).value++ // update globalVersion
|
||||||
|
c1.value
|
||||||
|
|
||||||
|
expect(spy).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
test('computed should remain live after losing all subscribers', () => {
|
test('computed should remain live after losing all subscribers', () => {
|
||||||
const state = reactive({ a: 1 })
|
const state = reactive({ a: 1 })
|
||||||
const p = computed(() => state.a + 1)
|
const p = computed(() => state.a + 1)
|
||||||
|
|
|
@ -49,6 +49,7 @@ export enum EffectFlags {
|
||||||
DIRTY = 1 << 4,
|
DIRTY = 1 << 4,
|
||||||
ALLOW_RECURSE = 1 << 5,
|
ALLOW_RECURSE = 1 << 5,
|
||||||
PAUSED = 1 << 6,
|
PAUSED = 1 << 6,
|
||||||
|
EVALUATED = 1 << 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -377,22 +378,22 @@ export function refreshComputed(computed: ComputedRefImpl): undefined {
|
||||||
}
|
}
|
||||||
computed.globalVersion = globalVersion
|
computed.globalVersion = globalVersion
|
||||||
|
|
||||||
const dep = computed.dep
|
|
||||||
computed.flags |= EffectFlags.RUNNING
|
|
||||||
// In SSR there will be no render effect, so the computed has no subscriber
|
// In SSR there will be no render effect, so the computed has no subscriber
|
||||||
// and therefore tracks no deps, thus we cannot rely on the dirty check.
|
// and therefore tracks no deps, thus we cannot rely on the dirty check.
|
||||||
// Instead, computed always re-evaluate and relies on the globalVersion
|
// Instead, computed always re-evaluate and relies on the globalVersion
|
||||||
// fast path above for caching.
|
// fast path above for caching.
|
||||||
|
// #12337 if computed has no deps (does not rely on any reactive data) and evaluated,
|
||||||
|
// there is no need to re-evaluate.
|
||||||
if (
|
if (
|
||||||
dep.version > 0 &&
|
|
||||||
!computed.isSSR &&
|
!computed.isSSR &&
|
||||||
computed.deps &&
|
computed.flags & EffectFlags.EVALUATED &&
|
||||||
!isDirty(computed)
|
((!computed.deps && !(computed as any)._dirty) || !isDirty(computed))
|
||||||
) {
|
) {
|
||||||
computed.flags &= ~EffectFlags.RUNNING
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
computed.flags |= EffectFlags.RUNNING
|
||||||
|
|
||||||
|
const dep = computed.dep
|
||||||
const prevSub = activeSub
|
const prevSub = activeSub
|
||||||
const prevShouldTrack = shouldTrack
|
const prevShouldTrack = shouldTrack
|
||||||
activeSub = computed
|
activeSub = computed
|
||||||
|
@ -402,6 +403,7 @@ export function refreshComputed(computed: ComputedRefImpl): undefined {
|
||||||
prepareDeps(computed)
|
prepareDeps(computed)
|
||||||
const value = computed.fn(computed._value)
|
const value = computed.fn(computed._value)
|
||||||
if (dep.version === 0 || hasChanged(value, computed._value)) {
|
if (dep.version === 0 || hasChanged(value, computed._value)) {
|
||||||
|
computed.flags |= EffectFlags.EVALUATED
|
||||||
computed._value = value
|
computed._value = value
|
||||||
dep.version++
|
dep.version++
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue