From 7161176cd0dff10d65ab58e266018aff2660610f Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Aug 2022 18:14:50 +0800 Subject: [PATCH] fix: fix effect scope tracking for manually created instances fix #12705 --- src/core/instance/init.ts | 1 + src/core/instance/lifecycle.ts | 2 -- src/core/observer/watcher.ts | 11 ++++++++++- src/v3/reactivity/effectScope.ts | 6 +++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/instance/init.ts b/src/core/instance/init.ts index 876c9ddbf96..91456c21920 100644 --- a/src/core/instance/init.ts +++ b/src/core/instance/init.ts @@ -34,6 +34,7 @@ export function initMixin(Vue: typeof Component) { vm.__v_skip = true // effect scope vm._scope = new EffectScope(true /* detached */) + vm._scope._vm = true // merge options if (options && options._isComponent) { // optimize internal component instantiation diff --git a/src/core/instance/lifecycle.ts b/src/core/instance/lifecycle.ts index fec330ad5fc..df70b7113fd 100644 --- a/src/core/instance/lifecycle.ts +++ b/src/core/instance/lifecycle.ts @@ -209,7 +209,6 @@ export function mountComponent( // we set this to vm._watcher inside the watcher's constructor // since the watcher's initial patch may call $forceUpdate (e.g. inside child // component's mounted hook), which relies on vm._watcher being already defined - vm._scope.on() new Watcher( vm, updateComponent, @@ -217,7 +216,6 @@ export function mountComponent( watcherOptions, true /* isRenderWatcher */ ) - vm._scope.off() hydrating = false // flush buffer for flush: "pre" watchers queued in setup() diff --git a/src/core/observer/watcher.ts b/src/core/observer/watcher.ts index 00bf19b9123..b2989b53772 100644 --- a/src/core/observer/watcher.ts +++ b/src/core/observer/watcher.ts @@ -71,7 +71,16 @@ export default class Watcher implements DepTarget { options?: WatcherOptions | null, isRenderWatcher?: boolean ) { - recordEffectScope(this, activeEffectScope || (vm ? vm._scope : undefined)) + recordEffectScope( + this, + // if the active effect scope is manually created (not a component scope), + // prioritize it + activeEffectScope && !activeEffectScope._vm + ? activeEffectScope + : vm + ? vm._scope + : undefined + ) if ((this.vm = vm) && isRenderWatcher) { vm._watcher = this } diff --git a/src/v3/reactivity/effectScope.ts b/src/v3/reactivity/effectScope.ts index bc15380eb4a..2ba50cd9ca8 100644 --- a/src/v3/reactivity/effectScope.ts +++ b/src/v3/reactivity/effectScope.ts @@ -27,10 +27,14 @@ export class EffectScope { * @internal */ scopes: EffectScope[] | undefined + /** + * indicates this being a component root scope + * @internal + */ + _vm?: boolean /** * track a child scope's index in its parent's scopes array for optimized * removal - * @internal */ private index: number | undefined