diff --git a/packages/runtime-core/__tests__/apiCreateApp.spec.ts b/packages/runtime-core/__tests__/apiCreateApp.spec.ts index f6386339741..3e31cf8e750 100644 --- a/packages/runtime-core/__tests__/apiCreateApp.spec.ts +++ b/packages/runtime-core/__tests__/apiCreateApp.spec.ts @@ -8,6 +8,7 @@ import { nextTick, nodeOps, onMounted, + onScopeDispose, provide, ref, resolveComponent, @@ -556,6 +557,26 @@ describe('api: createApp', () => { ).not.toHaveBeenWarned() }) + test('should invoke onScopeDispose when the app unmount', () => { + const spy = vi.fn(() => {}) + const root = nodeOps.createElement('div') + + const app = createApp({ + setup() { + return () => h('div') + }, + }) + + app.runWithContext(() => { + onScopeDispose(spy) + }) + + app.mount(root) + app.unmount() + + expect(spy).toHaveBeenCalledTimes(1) + }) + // #10005 test('flush order edge case on nested createApp', async () => { const order: string[] = [] diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index b3373dc8662..de6e6b7b277 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -1,3 +1,4 @@ +import { effectScope } from '@vue/reactivity' import { type Component, type ComponentInternalInstance, @@ -28,6 +29,7 @@ import { installAppCompatProperties } from './compat/global' import type { NormalizedPropsOptions } from './componentProps' import type { ObjectEmitsOptions } from './componentEmits' import type { DefineComponent } from './apiDefineComponent' +import type { EffectScope } from '@vue/reactivity' export interface App { version: string @@ -70,6 +72,7 @@ export interface App { _container: HostElement | null _context: AppContext _instance: ComponentInternalInstance | null + _scope: EffectScope /** * v2 compat only @@ -215,6 +218,7 @@ export function createAppAPI( rootProps = null } + const scope = effectScope(true) const context = createAppContext() const installedPlugins = new WeakSet() @@ -227,6 +231,7 @@ export function createAppAPI( _container: null, _context: context, _instance: null, + _scope: scope, version, @@ -371,6 +376,7 @@ export function createAppAPI( unmount() { if (isMounted) { + scope.stop() render(null, app._container) if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { app._instance = null @@ -399,7 +405,7 @@ export function createAppAPI( const lastApp = currentApp currentApp = app try { - return fn() + return app._scope.run(fn)! } finally { currentApp = lastApp }