今天主要学习Vue3中的数据监视:
ps: 代码中的注释写的很详细,这样更有利于理解
watch
作用: 监视数据的变化(和Vue2中watch作用一致)
特点: Vue3中的watch只能监视以下四种数据:
- ref创建定义的数据(基本类型、对象类型)
- reactive定义的数据(对象类型)
- 函数返回一个值(getter函数)
- 一个包含上述内容的数组
语法: watch接收三个参数:第一个参数是监视的对象;第二个参数是执行的回调函数(回调函数会收到两个值:新值和旧值);第三个参数是是否进行深度监视或者是否打开页面就监视
下面分情况概述:
情况一:监听ref定义的基本数据及对象数据
<template>
<div class="app">
<!-- <h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">点击修改姓名</button>
<button @click="changeAge">点击修改年龄</button> -->
<!-- ========================================================= -->
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="changeName">点击修改姓名</button>
<button @click="changeAge">点击修改年龄</button>
<button @click="changeperson">点击修改全部信息</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 知识点一:watch监视
// 首先 引入watch
// watch监视的是ref定义的基本响应式数据
import {ref,watch} from "vue"
// 数据
// const name=ref("张三")
// const age=ref(18)
// // 方法
// function changeName(){
// name.value+="~"
// }
// function changeAge(){
// age.value++
// }
// watch在vue2是配置项,在vue3中是函数。
// 对name进行监视
// watch(name,(newValue,oldValue)=>{
// console.log("name改变了",newValue,oldValue)
// })
// =========================================================
// 知识点二:watch监视的是ref定义的对象数据
const person=ref({
name:"张三",
age:18
})
function changeName(){
person.value.name+="~"
}
function changeAge(){
person.value.age++
}
function changeperson(){
person.value={name:"李四",age:19}
}
// 对person进行监视,此时只能监视到整个person的变化,而不能检测到person里属性的变化
// watch(person,(newValue,oldValue)=>{
// console.log("person改变了",newValue,oldValue)
// })
// 添加第三个参数,可以检测到person中属性name和age的变化
watch(person,(newValue,oldValue)=>{
console.log("person改变了",newValue,oldValue)
},{deep:true,immediate:true})
// =========================================================
// 注意:
// 进行深度监视后,name和age属性可以被监视到。
// 监测name和age返回的新值和旧值都是新值,因为他们是同一对象
// 监测整个person对象返回的分别是新值和旧值,因为他们不是同一对象,因为整个person都被修改了
</script>
<style>
.app {
background-color: #ddd;
box-shadow: 0 0 10px;
border-radius:10px;
padding: 20px;
}
</style>
情况二: 监视reactive定义的对象数据
<template>
<div class="app">
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="changeName">点击修改姓名</button>
<button @click="changeAge">点击修改年龄</button>
<button @click="changeperson">点击修改全部信息</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 知识点一:watch监视
// 首先 引入watch
// watch监视的是reactive定义的对象响应式数据
import {reactive,watch} from "vue"
const person=reactive({
name:"张三",
age:18
})
function changeName(){
person.name+="~"
}
function changeAge(){
person.age++
}
function changeperson(){
Object.assign(person,{name:"李四",age:20})
}
// 对person进行监视,此时只能监视到整个person的变化,也能能检测到person里属性的变化(reactive对象数据,默认开启深度监视
watch(person,(newValue,oldValue)=>{
console.log("person改变了",newValue,oldValue)
})
// =========================================================
// 注意:
// 监测name和age返回的新值和旧值(newValue和oldValue)都是新值,因为他们是同一对象
// 监测整个person对象返回的newValue和oldValue分别是新值和旧值,因为他们不是同一对象
// =========================================================
//总结:
//reactive定义的对象数据和ref相同,都是对象中的属性 返回的新值和旧值都是新值,而整个person对象返回的newValue和oldValue分别是新值和旧值
</script>
<style>
.app {
background-color: #ddd;
box-shadow: 0 0 10px;
border-radius:10px;
padding: 20px;
}
</style>
情况三:(函数返回一个值)监视一个getter函数
常用于监视某个属性
<template>
<div class="app">
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>汽车:{{person.car.C1}}-{{ person.car.C2 }}</h2>
<button @click="changeName">点击修改姓名</button>
<button @click="changeAge">点击修改年龄</button>
<button @click="changeC1">点击修改C1</button>
<button @click="changeC2">点击修改C2</button>
<button @click="changecar">点击修改汽车</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 知识点一:watch监视
// 首先 引入watch
// watch监视:函数返回一个值(getter函数)
import {reactive,watch} from "vue"
const person=reactive({
name:"张三",
age:18,
car:{
C1:"柯尼塞格",
C2:"布加迪威龙"
}
})
function changeName(){
person.name+="~"
}
function changeAge(){
person.age++
}
function changeC1(){
person.car.C1="奥迪"
}
function changeC2(){
person.car.C2="大众"
}
function changecar(){
person.car={C1:"特斯拉",C2:"小米"} //这里注意,由于car也是一个对象,所以不用用Object assign来定义
}
// =========================================================
// 要求一:只对name属性进行监视 此时需要写成getter函数(watch可以检测到getter函数),判断该属性是不是对象类型,不是对象类型,应写成函数式
// watch(()=>{return person.name},(newValue,oldValue)=>{
// 可简写为:
watch(()=>person.name,(newValue,oldValue)=>{
console.log("name改变了",newValue,oldValue)
})
//要求二:只对car属性进行监视 判断该属性是不是对象类型,是对象类型,应写成函数式(推荐),也可以直接写
watch(()=>person.car,(newValue,oldValue)=>{
console.log("car改变了",newValue,oldValue)
},{deep:true})
// =========================================================
// 总结:监视的是对象里的属性(注意:首先要满足是对象,不管是对象里的基本数据还是对象数据类型),最好都写成函数式,注意点:若是也需要监视对象内部,则需手动开启深度监视。
</script>
<style>
.app {
background-color: #ddd;
box-shadow: 0 0 10px;
border-radius:10px;
padding: 20px;
}
</style>
情况四:监视多个数据(包含上述内容的数组)
<template>
<div class="app">
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>汽车:{{person.car.C1}}-{{ person.car.C2 }}</h2>
<button @click="changeName">点击修改姓名</button>
<button @click="changeAge">点击修改年龄</button>
<button @click="changeC1">点击修改C1</button>
<button @click="changeC2">点击修改C2</button>
<button @click="changecar">点击修改汽车</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 知识点一:watch监视
// 首先 引入watch
// watch监视:监视上述内容的数组(多个数据)
import {reactive,watch} from "vue"
const person=reactive({
name:"张三",
age:18,
car:{
C1:"柯尼塞格",
C2:"布加迪威龙"
}
})
function changeName(){
person.name+="~"
}
function changeAge(){
person.age++
}
function changeC1(){
person.car.C1="奥迪"
}
function changeC2(){
person.car.C2="大众"
}
function changecar(){
person.car={C1:"特斯拉",C2:"小米"} //这里注意,由于car也是一个对象,所以不用用Object assign来定义
}
// =========================================================
// 对name属性和car对象里面的C1属性进行监视
watch([()=>person.name,()=>person.car.C1],(newValue,oldValue)=>{
console.log("name和car被修改了",newValue,oldValue)
},{deep:true})
// 此时newValue返回的是name和car.C1返回的新值组成的数组
</script>
<style>
.app {
background-color: #ddd;
box-shadow: 0 0 10px;
border-radius:10px;
padding: 20px;
}
</style>
watchEffect
watch对比watchEffect
1.都能监听响应式数据的变化,不同的是监听数据变化的方式不同
2. watch:要明确指出监视的数据,当需要监视的数据过多时,操作麻烦
3.watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性),它会自己分析。
<template>
<div class="app">
<h2>水温:{{temp}}</h2>
<h2>水位:{{height}}</h2>
<button @click="changeTemp">点击水温+10</button>
<button @click="changeHeight">点击水位+10</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 知识点:watchEffect监视
// 首先 引入watchEffect
import {ref,watch,watchEffect} from "vue"
const temp=ref(0)
const height=ref(10)
function changeTemp(){
temp.value+=10
}
function changeHeight(){
height.value+=10
}
// 要求:当水温大于60或水位大于80,向服务器发送请求
// 对水温和水位进行监视 (不是对象里的属性,可直接写)
// =========================================================
// 第一种写法:
// watch([temp,height],()=>{ //value表示newValue,返回的是newTemp和newHeight组成的数组
// // 解构
// // const [newTemp,newHeight]=value
// // 进行判断
// if(temp.value>60 || height.value>80){
// console.log("向服务器发送请求")
// }
// })
// 第二种写法:
// watch([temp,height],(value)=>{ //value表示newValue,返回的是temp和height的新值组成的数组
// // 进行判断
// if(value[0]>60 || value[1]>80){
// console.log("向服务器发送请求")
// }
// })
// 第三种写法:
// watch([temp,height],(value)=>{ //value表示newValue,返回的是newTemp和newHeight组成的数组
// // 解构
// const [newTemp,newHeight]=value
// // 进行判断
// if(newTemp>60 || newHeight>80){
// console.log("向服务器发送请求")
// }
// })
// =========================================================
// 使用watchEffect写:(直接使用,watchEffect会自己分析),适用于监视的对象足够多的情况
watchEffect(()=>{
if(temp.value>60 || height.value>80){
console.log("向服务器发送请求")
}
})
</script>
<style>
.app {
background-color: #ddd;
box-shadow: 0 0 10px;
border-radius:10px;
padding: 20px;
}
</style>