diff --git a/src/core/instance/init.ts b/src/core/instance/init.ts index 876c9ddbf9..91456c2192 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 fec330ad5f..df70b7113f 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 00bf19b912..b2989b5377 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 bc15380eb4..2ba50cd9ca 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