mirror of https://github.com/vuejs/core.git
fix(reactivity): ensure multiple effectScope on() and off() calls maintains correct active scope
close #12631
close #12632
This is a combination of changes from both 8dec243
and #12641
This commit is contained in:
parent
e8e842241a
commit
22dcbf3e20
|
@ -8,6 +8,10 @@ export class EffectScope {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
private _active = true
|
private _active = true
|
||||||
|
/**
|
||||||
|
* @internal track `on` calls, allow `on` call multiple times
|
||||||
|
*/
|
||||||
|
private _on = 0
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -99,20 +103,27 @@ export class EffectScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevScope: EffectScope | undefined
|
||||||
/**
|
/**
|
||||||
* This should only be called on non-detached scopes
|
* This should only be called on non-detached scopes
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
on(): void {
|
on(): void {
|
||||||
|
if (++this._on === 1) {
|
||||||
|
this.prevScope = activeEffectScope
|
||||||
activeEffectScope = this
|
activeEffectScope = this
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should only be called on non-detached scopes
|
* This should only be called on non-detached scopes
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
off(): void {
|
off(): void {
|
||||||
activeEffectScope = this.parent
|
if (this._on > 0 && --this._on === 0) {
|
||||||
|
activeEffectScope = this.prevScope
|
||||||
|
this.prevScope = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop(fromParent?: boolean): void {
|
stop(fromParent?: boolean): void {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
TrackOpTypes,
|
TrackOpTypes,
|
||||||
TriggerOpTypes,
|
TriggerOpTypes,
|
||||||
effectScope,
|
effectScope,
|
||||||
|
onScopeDispose,
|
||||||
shallowReactive,
|
shallowReactive,
|
||||||
shallowRef,
|
shallowRef,
|
||||||
toRef,
|
toRef,
|
||||||
|
@ -1982,4 +1983,31 @@ describe('api: watch', () => {
|
||||||
expect(spy1).toHaveBeenCalled()
|
expect(spy1).toHaveBeenCalled()
|
||||||
expect(spy2).toHaveBeenCalled()
|
expect(spy2).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #12631
|
||||||
|
test('this.$watch w/ onScopeDispose', () => {
|
||||||
|
const onCleanup = vi.fn()
|
||||||
|
const toggle = ref(true)
|
||||||
|
|
||||||
|
const Comp = defineComponent({
|
||||||
|
render() {},
|
||||||
|
created(this: any) {
|
||||||
|
this.$watch(
|
||||||
|
() => 1,
|
||||||
|
function () {},
|
||||||
|
)
|
||||||
|
onScopeDispose(onCleanup)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const App = defineComponent({
|
||||||
|
render() {
|
||||||
|
return toggle.value ? h(Comp) : null
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
createApp(App).mount(root)
|
||||||
|
expect(onCleanup).toBeCalledTimes(0)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue