Skip to content

Commit 74d2a76

Browse files
committed
fix(watch): fix flush: pre watchers triggered synchronously in setup
fix #5721
1 parent 82bdf86 commit 74d2a76

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

packages/runtime-core/__tests__/apiWatch.spec.ts

+29-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
h,
1919
createApp,
2020
watchPostEffect,
21-
watchSyncEffect
21+
watchSyncEffect,
22+
onMounted
2223
} from '@vue/runtime-test'
2324
import {
2425
ITERATE_KEY,
@@ -581,6 +582,33 @@ describe('api: watch', () => {
581582
expect(calls).toEqual(['render', 'watcher 1', 'watcher 2', 'render'])
582583
})
583584

585+
// #5721
586+
it('flush: pre triggered in component setup should be buffered and called before mounted', () => {
587+
const count = ref(0)
588+
const calls: string[] = []
589+
const App = {
590+
render() {},
591+
setup() {
592+
watch(
593+
count,
594+
() => {
595+
calls.push('watch ' + count.value)
596+
},
597+
{ flush: 'pre' }
598+
)
599+
onMounted(() => {
600+
calls.push('mounted')
601+
})
602+
// mutate multiple times
603+
count.value++
604+
count.value++
605+
count.value++
606+
}
607+
}
608+
render(h(App), nodeOps.createElement('div'))
609+
expect(calls).toMatchObject(['watch 3', 'mounted'])
610+
})
611+
584612
// #1852
585613
it('flush: post watcher should fire after template refs updated', async () => {
586614
const toggle = ref(false)

packages/runtime-core/src/apiWatch.ts

+1-9
Original file line numberDiff line numberDiff line change
@@ -345,15 +345,7 @@ function doWatch(
345345
scheduler = () => queuePostRenderEffect(job, instance && instance.suspense)
346346
} else {
347347
// default: 'pre'
348-
scheduler = () => {
349-
if (!instance || instance.isMounted) {
350-
queuePreFlushCb(job)
351-
} else {
352-
// with 'pre' option, the first call must happen before
353-
// the component is mounted so it is called synchronously.
354-
job()
355-
}
356-
}
348+
scheduler = () => queuePreFlushCb(job)
357349
}
358350

359351
const effect = new ReactiveEffect(getter, scheduler)

packages/runtime-core/src/scheduler.ts

+2
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ export function flushPreFlushCbs(
182182
}
183183

184184
export function flushPostFlushCbs(seen?: CountMap) {
185+
// flush any pre cbs queued during the flush (e.g. pre watchers)
186+
flushPreFlushCbs()
185187
if (pendingPostFlushCbs.length) {
186188
const deduped = [...new Set(pendingPostFlushCbs)]
187189
pendingPostFlushCbs.length = 0

0 commit comments

Comments
 (0)