一句总结:Vue3中的watch用于监听数据的变化并在变化时执行相应的回调函数,支持深度监听和监听多个数据源,是Vue 3响应式系统中处理数据变化的关键机制之一。
watch只能监视四种数据
- ref定义的数据
- reactive定义的数据
- 函数返回一个值
- 一个包含上述内容的数组
情况一:watch监视ref定义的基本类型数据
<template>
<div>
<h3>求和{{ sum }}</h3>
<button @click="changeSum">点我 + 1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref, watch } from "vue";
let sum = ref(0)
function changeSum() {
sum.value += 1
}
watch(sum, (newValue, oldValue)=>{
console.log("sum发生了变化", newValue, oldValue);
})
</script>
总结:
watch监视ref定义的基本类型数据,直接写数据名,不用.value,实际监视的是其value值的改变;watch调用会有一个返回值stopwatch,用于停止监听的函数
情况二:监视ref定义的对象类型数据
<template>
<div>
<div>姓名:{{ person.name }}</div>
<div>年龄:{{ person.age }}</div>
<button @click="changeName">修改姓名</button>
<button @click="changePerson">修改人</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref, watch } from "vue";
let person = ref({
name: 'zhangsan',
age: 20
})
function changeName() {
person.value.name = 'lisi'
}
function changePerson() {
person.value = {
name: 'lisi',
age: 10
}
}
const stopwatch = watch(person, (newValue, oldValue)=>{
console.log("sum发生了变化", newValue, oldValue);
}, {deep: true})
</script>
监视ref定义的对象类型数据,直接写数据名,监视的是对象的地址值,如果想监视对象内部的数据,需要手动使用
deep:true开启深度监视
watch监听ref定义的对象类型数据时,如果修改对象中某一个值,newValue和oldValue是一样的
因为对象的地址值没有发生变化
情况三:watch监听reactive定义的对象类型数据
<template>
<div>
<div>姓名:{{ person.name }}</div>
<div>年龄:{{ person.age }}</div>
<button @click="changeName">修改姓名</button>
<button @click="changePerson">修改人</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20
})
function changeName() {
person.name = 'lisi'
}
function changePerson() {
Object.assign(person, {
name: 'lisi',
age: 10
})
}
const stopwatch = watch(person, (newValue, oldValue)=>{
console.log("sum发生了变化", newValue, oldValue);
})
</script>
watch监听reactive定义的对象类型数据,隐式创建了深度监视
情况四:监视ref或reactive定义的对象类型数据中的某个数据
- 如果该属性是对象类型,可以直接写,也可以写成函数形式
- 如果该属性不是对象类型,需要写成函数形式
<template>
<div>
<div v-for="(game,index) in person.game" :key="index">
<span>{{game}}</span>
</div>
<button @click="changeName">修改姓名</button>
<button @click="changeGame1">修改游戏1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20,
game: {
game1: '三角洲行动',
game2: '1999'
}
})
function changeName() {
person.name = 'lisi'
}
function changeGame() {
person.game.game1 = '使命召唤'
}
watch(()=>person.name, (newValue, oldValue)=>{
console.log("name发生了变化", newValue, oldValue);
})
watch(()=>person.game.game1,(newValue, oldValue)=>{
console.log("game1发生了变化", newValue, oldValue);
})
</script>
如果该属性是对象类型,直接写监听不到数据的变化,因为已经不是原来的对象
<template>
<div>
<div v-for="(game,index) in person.game" :key="index">
<span>{{game}}</span>
</div>
<button @click="changeGame">修改游戏</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20,
game: {
game1: '三角洲行动',
game2: '1999'
}
})
function changeGame() {
person.game = {
game1: '使命召唤',
game2: '崩铁'
}
}
watch(person.game,(newValue, oldValue)=>{
console.log("game1发生了变化", newValue, oldValue);
})
</script>
这时就需要写成函数形式
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20,
game: {
game1: '三角洲行动',
game2: '1999'
}
})
function changeGame() {
person.game = {
game1: '使命召唤',
game2: '崩铁'
}
}
watch(()=>person.game,(newValue, oldValue)=>{
console.log("game1发生了变化", newValue, oldValue);
})
</script>
监视多个数据
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20,
game: {
game1: '三角洲行动',
game2: '1999'
}
})
function changeName() {
person.name = 'lisi'
}
function changeGame() {
person.game = {
game1: '使命召唤',
game2: '崩铁'
}
}
watch([()=>person.name, ()=>person.game],(newValue, oldValue)=>{
console.log("game1发生了变化", newValue, oldValue);
})
</script>
watchEffect
立即运行一个函数,同时响应式的追踪其依赖,并在依赖更改时重新执行该函数;也就是函数中用到哪些属性,就监听哪些属性
<template>
<div>
<div>{{ person.age }}</div>
<button @click="changeAge">修改年龄</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, watchEffect } from "vue";
let person = reactive({
name: 'zhangsan',
age: 20,
})
function changeAge() {
person.age += 1
}
watchEffect(()=>{
if(person.age >= 30) {
console.log("而立");
}
})
</script>