watchEffect automatically tracks all reactive dependencies used inside it.
1<script setup>
2import { ref, watchEffect } from 'vue'
3
4const count = ref(0)
5const message = ref('Hello')
6
7// Automatically tracks count and message
8watchEffect(() => {
9 console.log(`Count: ${count.value}, Message: ${message.value}`)
10})
11
12// Will be called:
13// 1. Immediately on initialization
14// 2. When count changes
15// 3. When message changes
16</script>1import { ref, watch, watchEffect } from 'vue'
2
3const count = ref(0)
4
5// watch - explicit source, access to oldValue
6watch(count, (newVal, oldVal) => {
7 console.log(`${oldVal} → ${newVal}`)
8})
9
10// watchEffect - automatic tracking, no oldValue
11watchEffect(() => {
12 console.log(`Count: ${count.value}`)
13})| Feature | watch | watchEffect | |-------|-------|-------------| | Source | Explicit | Automatic | | oldValue | Yes | No | | immediate | Optional | Always | | Lazy | Yes | No |
1<script setup>
2import { ref, watchEffect } from 'vue'
3
4const id = ref(1)
5
6watchEffect((onCleanup) => {
7 const controller = new AbortController()
8
9 fetch(`/api/artwork/${id.value}`, {
10 signal: controller.signal
11 })
12 .then(res => res.json())
13 .then(data => console.log(data))
14
15 // Cleanup - called before each re-run
16 onCleanup(() => {
17 controller.abort()
18 })
19})
20</script>1import { watchEffect, watchPostEffect, watchSyncEffect } from 'vue'
2
3// Default - before DOM update
4watchEffect(() => { /* ... */ })
5
6// After DOM update
7watchPostEffect(() => {
8 // DOM is already updated here
9})
10
11// Synchronously - immediately on change
12watchSyncEffect(() => {
13 // Warning: may affect performance
14})