目录
情况三:监视【reactive】定义的【对象类型】数据 , 默认开启了深度监视。
情况四: 监视ref或reactive定义的【对象类型】数据中的某个属性
watch
作用:监视数据的变化(和vue2中的watch作用一致)
特点:vue3中的watch只能监视以下四种数据
1、ref定义的数据
2、reactive定义的数据
3、函数返回一个值(getter函数)。
4、一个包含上述内容的数组。
我们在Vue3中使用watch的时候,通常会遇到以下几种情况:
情况一:监视【ref】定义的【基本类型】数据
监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。
<script setup lang="ts">
import {ref,watch} from 'vue'
let sum = ref(0)
function changeSum(){
sum.value++
}
//监视
let stopwatch = watch(sum,(newVal,oldVal)=>{
console.log('sum变化了',newVal,oldVal)
if(newVal>=10){
stopwatch()//停止监视
}
})
console.log(stopwatch)
/**
* () => {
effect2.stop();
if (scope) {
remove(scope.effects, effect2);
}
}
*/
</script>
<template>
<h1>情况一:监视【ref】定义的基本类型数据</h1>
<div class="">
<h2>当前求和为{{ sum }}</h2>
<button @click="changeSum">点我sum+1</button>
</div>
</template>
<style scoped>
</style>
情况二:监视【ref】定义的【对象类型】数据
监视的是对象的地址值。若想监视对象内部属性的变化,需要手动开启deep属性
- watch的第一个参数是:被监视的数据
- watch的第二个参数是:监视的回调
- watch的第三个参数是:配置对象(deep,immediate等等...)
注意:
- 若修改的是ref定义的对象中的属性,newVal和oldVal都是新值,因为他们是同一个对象
- 若修改整个ref定义的对象,newVal是新值,oldVal是旧值,因为不是同一个对象了
<script setup lang="ts">
import {ref,watch} from 'vue'
let person = ref({
name:"张三",
age:18
})
function changePersonName(){
person.value.name+='&'
//watch的时候,newVal和oldVal相等,都是新的perosn.name的值
}
function changePersonAge(){
person.value.age+=1
//watch的时候,newVal和oldVal相等,都是新的perosn.age的值
}
function changePerson(){
// person.value.name+='&'
// person.value.age+=1
person.value = {
name:"1",
age:2
}
//watch的时候,newVal和oldVal不相等,newVal是person的新值,old是person的旧值
}
//监视
/**
* 监视的是对象的地址值,
* 若想监视对象内部属性的变化,需要手动开启deep属性
*/
let stopwatch = watch(person,(newVal,oldVal)=>{
console.log('变化了',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
},{deep:true})
console.log(stopwatch)
/**
* () => {
effect2.stop();
if (scope) {
remove(scope.effects, effect2);
}
}
*/
</script>
<template>
<h1>情况二:监视【ref】定义的【对象类型】数据</h1>
<div class="">
<h2>姓名:{{person.name}}</h2>
<h2>姓名:{{person.age}}</h2>
<button @click="changePersonName">点我改name</button>
<button @click="changePersonAge">点我改age</button>
<button @click="changePerson">点我改所有</button>
</div>
</template>
<style scoped>
</style>
情况三:监视【reactive】定义的【对象类型】数据 , 默认开启了深度监视。
function changePerson(){ //reactive修饰的对象,不可整体修改 // person = { // name:"1", // age:2 // } //ref修饰的对象【 person.value = .. 】是重新给对象赋制,对象的地址已经发生变化了。 //reactive修饰的对象,做以下操作时是批量修改person的属性。对象的地址没有发生变化。 Object.assign(person,{name:"hei",age:100}) }
<script setup lang="ts">
import {reactive,watch} from 'vue'
let person = reactive({
name:"张三",
age:18
})
function changePersonName(){
person.name+='&'
}
function changePersonAge(){
person.age+=1
}
function changePerson(){
//reactive修饰的对象,不可整体修改
// person = {
// name:"1",
// age:2
// }
//ref修饰的对象【 person.value = .. 】是重新给对象赋制,对象的地址已经发生变化了。
//reactive修饰的对象,做以下操作时是批量修改person的属性。对象的地址没有发生变化。
Object.assign(person,{name:"hei",age:100})
}
//监视
watch(person,(newVal,oldVal)=>{
console.log('变化了',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
})
</script>
<template>
<h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
<div class="">
<h2>姓名:{{person.name}}</h2>
<h2>姓名:{{person.age}}</h2>
<button @click="changePersonName">点我改name</button>
<button @click="changePersonAge">点我改age</button>
<button @click="changePerson">点我改所有</button>
</div>
</template>
<style scoped>
</style>
情况四: 监视ref或reactive定义的【对象类型】数据中的某个属性
注意:
- 若该属性值不是【对象类型】,需要写成函数形式。
- 若该属性值依然是【对象类型】,可以直接编,也可以写成函数,不过建议写成函数
- 若该属性值依然是【对象类型】,监视的是地址值,若是需要关注对象内部,需要手动开启深度监视
<script setup lang="ts">
import {reactive,watch} from 'vue'
let person = reactive({
name:"张三",
age:18,
car:{
c1:"比亚迪",
c2:"宝马",
}
})
function changePersonName(){
person.name+='&'
}
function changePersonAge(){
person.age+=1
}
function changeC1(){
person.car.c1 = '特斯拉'
}
function changeC2(){
person.car.c2 = '劳斯莱斯'
}
function changeCar(){
person.car = {
c1:"小米汽车",
c2:"QQ飞车"
}
}
//监视name:监视响应式对象中的某个属性。且该属性是基本类型的,要写成函数式
watch(()=>{return person.name},(newVal,oldVal)=>{
console.log('name变化了',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
})
//监视age
watch(()=>person.age,(newVal,oldVal)=>{
console.log('age变化了',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
})
//监视person.car对象【点击“changeCar”按钮,watch监听不到,怎么解决?写成函数式】
// watch(person.car,(newVal,oldVal)=>{
// console.log('person.car',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
// })
//监视car:监视响应式对象中的某个属性。且该属性是对象类型的,可以直接写,也能写函数,更推荐写成函数式
watch(()=>{return person.car},(newVal,oldVal)=>{
console.log('person.car',newVal,oldVal) //变化了 Proxy(Object) {name: '1', age: 2} Proxy(Object) {name: '1', age: 2}
},{deep:true})//手动开启deep
</script>
<template>
<h1>情况四:监视ref或reactive定义的【对象类型】数据中的某个属性</h1>
<div class="">
<h2>姓名:{{person.name}}</h2>
<h2>姓名:{{person.age}}</h2>
<h2>汽车{{person.car.c1}}</h2>
<h2>汽车{{person.car.c2}}</h2>
<button @click="changePersonName">点我改name</button>
<button @click="changePersonAge">点我改age</button>
<button @click="changeC1">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改整个车</button>
</div>
</template>
<style scoped>
</style>
情况五: 监视上述多个数据
第一种,值也用数组
第一种,值不用数组
<script setup lang="ts">
import {reactive,watch} from 'vue'
let person = reactive({
name:"张三",
age:18,
car:{
c1:"比亚迪",
c2:"宝马",
}
})
function changePersonName(){
person.name+='&'
}
function changeC1(){
person.car.c1 = '特斯拉'
}
//监视上述多个数据
watch([()=>{return person.name},()=>{return person.car.c1}],(newVal,oldVal)=>{
console.log('变化了',newVal,oldVal)
})
</script>
<template>
<h1>情况五:监视上述多个数据</h1>
<div class="">
<h2>姓名:{{person.name}}</h2>
<h2>姓名:{{person.age}}</h2>
<h2>汽车{{person.car.c1}}</h2>
<h2>汽车{{person.car.c2}}</h2>
<button @click="changePersonName">点我改name</button>
<button @click="changeC1">修改第一台车</button>
</div>
</template>
<style scoped>
</style>
watchEffect
官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
watch对比watchEffect
- 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
- watch:要明确指出监视的数据
- watchEffect:不同明确指出监视的数据(函数中用到哪些水性,那就监视哪些属性)。
<script setup lang="ts">
import {ref,watch,watchEffect} from 'vue'
let temp = ref(10)
let height = ref(0)
function changeTemp(){
temp.value+=10
}
function changeHeight(){
height.value+=1
}
//监视
// let stopwatch = watch(sum,(newVal,oldVal)=>{
// console.log('sum变化了',newVal,oldVal)
// if(newVal>=10){
// stopwatch()//停止监视
// }
// })
watch([temp,height],([t,h])=>{
console.log(t,h)
// let [t,h] = newVal
if(t>=60||h>=10){
console.log('ok')
}
})
//当temp和height变化的时候,就会触发
watchEffect(()=>{
if(temp.value>=60||height.value>=10){
console.log('ok')
}
})
</script>
<template>
<div class="">
<h2>当水温达到60度,或水位达到10米,发送请求</h2>
<h2>当前水温:{{ temp }}℃</h2>
<h2>当前水位:{{ height }}米</h2>
<button @click="changeTemp">水温+10</button>
<button @click="changeHeight">高度+1</button>
</div>
</template>
<style scoped>
</style>