diff --git a/src/core/instance/lifecycle.ts b/src/core/instance/lifecycle.ts index 5c559daaa23..171c4e5d9a5 100644 --- a/src/core/instance/lifecycle.ts +++ b/src/core/instance/lifecycle.ts @@ -218,15 +218,17 @@ export function mountComponent( ) hydrating = false + // flush buffer for flush: "pre" watchers queued in setup() + const preWatchers = vm._preWatchers + if (preWatchers) { + for (let i = 0; i < preWatchers.length; i++) { + preWatchers[i].run() + } + } + // manually mounted instance, call mounted on self // mounted is called for render-created child components in its inserted hook if (vm.$vnode == null) { - const preWatchers = vm._preWatchers - if (preWatchers) { - for (let i = 0; i < preWatchers.length; i++) { - preWatchers[i].run() - } - } vm._isMounted = true callHook(vm, 'mounted') } diff --git a/test/unit/features/v3/apiWatch.spec.ts b/test/unit/features/v3/apiWatch.spec.ts index 9a7bcd9410f..85ee2ef8400 100644 --- a/test/unit/features/v3/apiWatch.spec.ts +++ b/test/unit/features/v3/apiWatch.spec.ts @@ -336,6 +336,23 @@ describe('api: watch', () => { expect(result2).toBe(true) }) + // #12569 + it('flush:pre watcher triggered before component mount (in child components)', () => { + const count = ref(0) + const spy = vi.fn() + const Comp = { + setup() { + watch(count, spy) + count.value++ + return h => h('div') + } + } + new Vue({ + render: h => h(Comp) + }).$mount() + expect(spy).toHaveBeenCalledTimes(1) + }) + it('flush timing: post', async () => { const count = ref(0) let result