Skip to content

Commit 80e2128

Browse files
committed
add more details for watcher flush timing
related: - vuejs/core#7030 - vuejs/core#10136
1 parent 0a3f144 commit 80e2128

File tree

1 file changed

+56
-4
lines changed

1 file changed

+56
-4
lines changed

src/guide/essentials/watchers.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,17 @@ For examples like these, with only one dependency, the benefit of `watchEffect()
331331

332332
When you mutate reactive state, it may trigger both Vue component updates and watcher callbacks created by you.
333333

334-
By default, user-created watcher callbacks are called **before** Vue component updates. This means if you attempt to access the DOM inside a watcher callback, the DOM will be in the state before Vue has applied any updates.
334+
Similar to component updates, user-created watcher callbacks are batched to avoid duplicate invocations. For example, we probably don't want a watcher to fire a thousand times if we synchronously push a thousand items into an array being watched.
335335

336-
If you want to access the DOM in a watcher callback **after** Vue has updated it, you need to specify the `flush: 'post'` option:
336+
By default, a watcher's callback is called **after** parent component updates (if any), and **before** the owner component's DOM updates. This means if you attempt to access the owner component's own DOM inside a watcher callback, the DOM will be in a pre-update state.
337+
338+
### Post Watchers
339+
340+
If you want to access the owner component's DOM in a watcher callback **after** Vue has updated it, you need to specify the `flush: 'post'` option:
337341

338342
<div class="options-api">
339343

340-
```js
344+
```js{6}
341345
export default {
342346
// ...
343347
watch: {
@@ -353,7 +357,7 @@ export default {
353357

354358
<div class="composition-api">
355359

356-
```js
360+
```js{2,6}
357361
watch(source, callback, {
358362
flush: 'post'
359363
})
@@ -375,6 +379,54 @@ watchPostEffect(() => {
375379

376380
</div>
377381

382+
### Sync Watchers
383+
384+
It's also possible to create a watcher that fires synchronously, before any Vue-managed updates:
385+
386+
<div class="options-api">
387+
388+
```js{6}
389+
export default {
390+
// ...
391+
watch: {
392+
key: {
393+
handler() {},
394+
flush: 'sync'
395+
}
396+
}
397+
}
398+
```
399+
400+
</div>
401+
402+
<div class="composition-api">
403+
404+
```js{2,6}
405+
watch(source, callback, {
406+
flush: 'sync'
407+
})
408+
409+
watchEffect(callback, {
410+
flush: 'sync'
411+
})
412+
```
413+
414+
Sync `watchEffect()` also has a convenience alias, `watchSyncEffect()`:
415+
416+
```js
417+
import { watchSyncEffect } from 'vue'
418+
419+
watchSyncEffect(() => {
420+
/* executed synchronously upon reactive data change */
421+
})
422+
```
423+
424+
</div>
425+
426+
:::warning Use with Caution
427+
Sync watchers do not have batching and triggers every time a reactive mutation is detected. It's ok to use them to watch simple boolean values, but avoid using them on data sources that might be synchronously mutated many times, e.g. arrays.
428+
:::
429+
378430
<div class="options-api">
379431

380432
## `this.$watch()` \* {#this-watch}

0 commit comments

Comments
 (0)