持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
问题抛出
watch 函数用来侦听特定的数据源,并在回调函数中执行副作用
- watch有三个参数:
参数1:监听的参数
参数2:监听的回调函数
参数3:监听的配置(immediate)
在Vue3中,在一些情况下,watch监听失效
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(obj, (newValue) => {
console.log(newValue)
})
</script>
<template>
<p>{{ obj.eat }}</p>
<button @click="obj.eat = '面条'"><code>obj.eat = '面条'</code></button>
</template>
问题解决
解决 1:修改第 1 层
因为 watch 对 ref 数据的监听默认是浅监听的,既然是浅监听,那可以直接修改第一层就好啦,也就是 obj.value。
<template>
<button @click="obj = { eat: '面条' }"><code>obj = { eat: '面条' }</code></button>
</template>
解决 2:开启深度监听
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(
obj,
(newValue) => {
console.log(newValue) // Proxy { eat: '面条' }
},
// #2
{ deep: true }
)
</script>
<template>
<p>{{ obj.eat }}</p>
<!-- #1 -->
<button @click="obj.eat = '面条'"><code>obj.eat = '面条'</code></button>
</template>
解决 3:监听 reactive
obj.value 是一个 reactive 数据,而 reactive 数据是开启深度监听的,并且不能修改。
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(obj.value, (newValue) => {
console.log(newValue) // Proxy { eat: '面条' }
})
</script>
<template>
<p>{{ obj.eat }}</p>
<button @click="obj.eat = '面条'"><code>修改 obj.eat</code></button>
</template>
🤔 注意:直接监听 reactive,对 reactive 本身的修改是不会触发监听的。
<button @click="obj = { eat: '面条' }"><code>obj = { eat: '面条' }</code></button>
解决 4:watch 指定函数,返回 ref
任何情况都不会触发监听,除非开启 deep。
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(
() => obj,
(newValue) => {
console.log(newValue)
}
)
</script>
<template>
<p>{{ obj.eat }}</p>
<button @click="obj.eat = '面条'"><code>obj.eat = '面条'</code></button>
<button @click="obj = { eat: '面条' }"><code>obj = { eat: '馒头' }</code></button>
</template>
解决 5:watch 指定函数,返回 reactive(ref 中的对象)
对这个 reactive 本身的修改会触发监听,内部数据的变化则不会。开启 deep 后上面 2 种情况都会被触发监听。
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(
() => obj.value,
(newValue) => {
console.log(newValue)
}
)
</script>
<template>
<p>{{ obj.eat }}</p>
<button @click="obj.eat = '面条'"><code>obj.eat = '面条'</code></button>
<button @click="obj = { eat: '馒头' }"><code>obj = { eat: '馒头' }</code></button>
</template>
解决 6:watch 指定函数,返回 reactive(直接定义的对象)
对这个 reactive 本身的修改和内部数据的变化都不会触发监听。开启 deep 后第 2 种情况会被触发监听。
解决 7:watch 指定函数,返回普通值
任何影响到此值的修改并且是响应式的,都会触发监听。
<script setup lang="ts">
import { watch, ref } from 'vue'
const obj = ref({
eat: '西瓜',
})
watch(
() => obj.value.eat,
(newValue) => {
console.log(newValue)
}
)
</script>
<template>
<p>{{ obj.eat }}</p>
<button @click="obj.eat = '面条'"><code>obj.eat = '面条'</code></button>
<button @click="obj = { eat: '馒头' }"><code>obj = { eat: '馒头' }</code></button>
</template>
今天就先写到这里了!!撒由那拉