上篇文章 :【Vue】Vue3.0(十一)Vue 3.0 中 computed 计算属性概念、使用及示例
🏡作者主页:点击!
🤖Vue专栏:点击!
⏰️创作时间:2024年10月16日12点45分
文章目录
-
- 【watch】作用
- 在`Vue3`中使用`watch`的时候,通常会遇到以下几种情况:
-
- [情况一 监视`ref`定义的【基本类型】数据](#情况一 监视
ref
定义的【基本类型】数据) - [情况二 监视`ref`定义的【对象类型】数据](#情况二 监视
ref
定义的【对象类型】数据) - [情况三 监视`reactive`定义的【对象类型】数据](#情况三 监视
reactive
定义的【对象类型】数据) - [情况四 监视`ref`或`reactive`定义的【对象类型】数据中的**某个属性*](#情况四 监视
ref
或reactive
定义的【对象类型】数据中的**某个属性*) - [* 情况五](#* 情况五)
- [情况一 监视`ref`定义的【基本类型】数据](#情况一 监视
- 总结注意点:
【watch】作用
- 作用:监视数据的变化(和
Vue2
中的watch
作用一致) - 特点:
Vue3
中的watch
只能监视以下四种数据:
ref
定义的数据。reactive
定义的数据。- 函数返回一个值(
getter
函数)。- 一个包含上述内容的数组。
在Vue3
中使用watch
的时候,通常会遇到以下几种情况:
情况一 监视ref
定义的【基本类型】数据
监视ref
定义的【基本类型】数据:直接写数据名即可,监视的是其value
值的改变。
html
<template>
<div class="person">
<h1>情况一:监视【ref】定义的【基本类型】数据</h1>
<h2>当前求和为:{{sum}}</h2>
<button @click="changeSum">点我sum+1</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,watch} from 'vue'
// 数据
let sum = ref(0)
// 方法
function changeSum(){
sum.value += 1
}
// 监视,情况一:监视【ref】定义的【基本类型】数据
const stopWatch = watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
if(newValue >= 10){
stopWatch()
}
})
</script>
情况二 监视ref
定义的【对象类型】数据
监视ref
定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视。
注意:
若修改的是
ref
定义的对象中的属性,newValue
和oldValue
都是新值,因为它们是同一个对象。若修改整个
ref
定义的对象,newValue
是新值,oldValue
是旧值,因为不是同一个对象了。
代码:
使用ref定义对象类型数据:
html
<template>
<div class="person">
<h2>情况2:watch监控ref定义的对象类型数据</h2>
<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">
import { reactive, ref,computed ,watch} from 'vue'
//数据
let person =ref({
name:'张三',age:19
})
//方法
function changeName(){
person.value.name+='~';
}
function changeAge(){
person.value.age+=1;
}
//修改整个人
function changePerson(){
person.value={name:'lis',age:20};
}
//watch监视对象的时候,监视的是对象的地址值,并不关心对象内部的属性的值是否变化;如果想要监控对象内部的属性的值,
//,需要手动开启内部监视
//watch参数:第一个参数:监控的对象
//watch参数:第二个参数:回调函数
//watch参数:第三个参数:配置对象(deep、inmidiate等)
watch(person,(newVal,oldVal)=>{
console.log(newVal,oldVal);
},{deep:true})
</script>
<style>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
li {
font: 1em sans-serif;
}
</style>
情况三 监视reactive
定义的【对象类型】数据
结论:监视reactive
定义的【对象类型】数据,且默认开启了深度监视。
使用reactive定义对象类型数据
html
<template>
<div class="person">
<h2>情况2:watch监控ref定义的对象类型数据</h2>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<button @click="changeName">修改姓名</button>
<button @click="changeAge">修改年龄</button>
<button @click="changePerson">修改整个人</button>
<hr />
<h2>obj:{{ obj.a.b.c }}</h2>
<button @click="changeObj">修改OBJ</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, ref, computed, watch } from 'vue'
//数据
let person = reactive({
name: '张三', age: 19
})
let obj = reactive({
a: {
b: {
c: 777
}
}
})
//方法
function changeName() {
person.name += '~';
}
function changeAge() {
person.age += 1;
}
//修改整个人
function changePerson() {
Object.assign(person, { name: '李四', age: 99 });
}
function changeObj() {
obj.a.b.c = 222;
}
//监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的
watch(person, (newVal, oldVal) => {
console.log('reactive定义的 person对象类型数据变化了', newVal, oldVal);
})
//第二个监控函数
watch(obj,(newVal,oldVal)=>{
console.log('reactive定义的 person对象类型数据变化了', newVal, oldVal);
})
</script>
<style>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
li {
font: 1em sans-serif;
}
</style>
情况四 监视ref
或reactive
定义的【对象类型】数据中的**某个属性*
监视ref
或reactive
定义的【对象类型】数据中的某个属性,注意点如下:
- 若该属性值不是 【对象类型】,需要写成函数形式。
代码:
html
<template>
<div class="person">
<h2>情况4:watch监控ref定义的对象类型数据</h2>
<h3>姓名:{{person.name}} </h3>
<h3>年龄:{{person.age}} </h3>
<h3>汽车:{{person.car.c1}} /{{person.car.c2}} </h3>
<button @click="changeName">修改姓名</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改c1</button>
<button @click="changeC2">修改c2</button>
<button @click="changeCar">修改Car</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, ref, computed, watch } from 'vue'
//数据
let person=reactive({
name:'张三',
age:18,
car:{
c1:'宝马',
c2:'奔驰'
}
})
function changeName(){
person.name+='~';
}
function changeAge(){
person.age+=1;
}
function changeC1(){
person.car.c1='大众1'
}
function changeC2(){
person.car.c2='大众2'
}
function changeCar(){
person.car={c1:'雅迪',c2:'艾玛'}
}
//watch监控reactive定义的对象类型数据中的某个属性,且该属性是一个基本类型的数据,则该属性需要写成一个有返回值的函数
watch(()=>{return person.name},(newVal,oldVal)=>{
console.log('person.name变化了',newVal,oldVal);
})
</script>
<style>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
li {
font: 1em sans-serif;
}
</style>
结果:(1)点击修改除了姓名以外的属性,触发不了监控,
(2)修改name属性,触发了监控中的输出
- 若该属性值是依然 是【对象类型】,可直接编,也可写成函数,建议写成函数(这种的)
验证代码:
html
<template>
<div class="person">
<h2>情况4:watch监控ref定义的对象类型数据</h2>
<h3>姓名:{{person.name}} </h3>
<h3>年龄:{{person.age}} </h3>
<h3>汽车:{{person.car.c1}} /{{person.car.c2}} </h3>
<button @click="changeName">修改姓名</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeC1">修改c1</button>
<button @click="changeC2">修改c2</button>
<button @click="changeCar">修改Car</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive, ref, computed, watch } from 'vue'
//数据
let person=reactive({
name:'张三',
age:18,
car:{
c1:'宝马',
c2:'奔驰'
}
})
function changeName(){
person.name+='~';
}
function changeAge(){
person.age+=1;
}
function changeC1(){
person.car.c1='大众1'
}
function changeC2(){
person.car.c2='大众2'
}
function changeCar(){
person.car={c1:'雅迪',c2:'艾玛'}
}
//情况4、watch监控reactive定义的对象类型数据中的某个属性,且该属性是一个基本类型的数据,则该属性需要写成一个有返回值的函数
// watch(()=>{return person.name},(newVal,oldVal)=>{
// console.log('person.name变化了',newVal,oldVal);
// })
watch(()=>{return person.car},(newVal,oldVal)=>{
console.log('person.car变化了',newVal,oldVal);
},{deep:true})
</script>
<style>
.person {
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 20px;
}
li {
font: 1em sans-serif;
}
</style>
结果:
写法一:当写法是:
typescript
watch(()=>person.car,(newVal,oldVal)=>{
console.log('person.car变化了',newVal,oldVal);
},{deep:true})
效果: 此时修改单个属性会被watch监视到,修改整个对象不会引起,
写法二、当写法是 : 监控的内容写成了对象的形式,此时函数返回的是地址,
typescript
watch(()=>{return person.car},(newVal,oldVal)=>{
console.log('person.car变化了',newVal,oldVal);
})
效果: 此时修改单个属性不会被watch监控到,修改整个person.car对象,也就是地址变化才会被watch监视到。
写法三、当写法是:
相交于第二种写法,加了一个watch的参数,此时就既能监控到其中每个属性的变化,又能监控到整体的变化了。
typescript
watch(()=>{return person.car},(newVal,oldVal)=>{
console.log('person.car变化了',newVal,oldVal);
},{deep:true})
效果: 单个属性和对象整体的变化都能引起watch函数的执行。
_结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。
* 情况五
监视上述的多个数据
html
<template>
<div class="person">
<h1>情况五:监视上述的多个数据</h1>
<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">修改第一台车</button>
<button @click="changeC2">修改第二台车</button>
<button @click="changeCar">修改整个车</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {reactive,watch} from 'vue'
// 数据
let person = reactive({
name:'张三',
age:18,
car:{
c1:'奔驰',
c2:'宝马'
}
})
// 方法
function changeName(){
person.name += '~'
}
function changeAge(){
person.age += 1
}
function changeC1(){
person.car.c1 = '奥迪'
}
function changeC2(){
person.car.c2 = '大众'
}
function changeCar(){
person.car = {c1:'雅迪',c2:'爱玛'}
}
// 监视,情况五:监视上述的多个数据
watch([()=>person.name,person.car],(newValue,oldValue)=>{
console.log('person.car变化了',newValue,oldValue)
},{deep:true})
</script>
结果:修改name、car.c1、car.c2都能被watch监控到
总结注意点:
综合上面的内容:进行的总结
- 1、ref定义的对象类型数据和reactive定义的对象类型数据,ref定义的对象数据,(let person =ref({ name:'张三',age:19 }) 已经定义了Person对象) 可以通过 person对象
={name:'李四',age:'20'}这种的直接让Person这个变量的地址指向一个新的对象;直接改变了地址 而reactive定义的对象,不能通过person对象
={name:'李四',age:'20'},因为不允许整个对象的修改,只允许里面某个属性的修改,如果非要对象中所有的属性都修改的话,就需要用到assign函数,第一个参数是要修改的老对象
第二个参数是修改成新的对象是啥- 2、watch对于ref和reactive定义的对象类型数据,监控有什么区别呢?前者默认不开启深度监视,后者默认开始深度监视
- 3、当响应对象是通过reactive对象定义的,那无论这个对象中的任何一个属性有变化,watch函数都能监控到。而且对reactive定义的对象的监听是隐式开启了
深层监听,而且是关不掉的;- 4、ref定义的对象,在使用watch监视的时候,第二个参数中的返回值,会有时候是不同的,有时候是相同的,如果只是修改ref锁定义的对象中的一个属性,则newVal和OldVal是一样的,
如果将一个新的对象给了ref定义的响应对象的value,那么此时Person指向的是一个新的对象的地址,相当于地址变了,此时newVal和oldVal是不一样的
而对于reactive定义的响应类型的对象数据,无论变所有属性,还是单个属性,他的地址都是不变的,所以newVal和oldVal都是一样的;- 5、watch中的第一个参数,可以是普通对象、ref定义的对象、reactive定义的对象,或者由上面形成的数组