当前位置: 首页 > article >正文

【Vue】Vue3.0 (十二)、watch对ref定义的基本类型、对象类型;reactive定义的对象类型的监视使用

上篇文章:【Vue】Vue3.0(十一)Vue 3.0 中 computed 计算属性概念、使用及示例

🏡作者主页:点击!

🤖Vue专栏:点击!

⏰️创作时间:2024年10月16日12点45分

文章目录

    • 【watch】作用
    • 在`Vue3`中使用`watch`的时候,通常会遇到以下几种情况:
      • 情况一 监视`ref`定义的【基本类型】数据
      • 情况二 监视`ref`定义的【对象类型】数据
      • 情况三 监视`reactive`定义的【对象类型】数据
      • 情况四 监视`ref`或`reactive`定义的【对象类型】数据中的**某个属性*
      • * 情况五
    • 总结注意点:

【watch】作用

  • 作用:监视数据的变化(和Vue2中的watch作用一致)
  • 特点:Vue3中的watch只能监视以下四种数据
  1. ref定义的数据。
  2. reactive定义的数据。
  3. 函数返回一个值(getter函数)。
  4. 一个包含上述内容的数组。

Vue3中使用watch的时候,通常会遇到以下几种情况:

情况一 监视ref定义的【基本类型】数据

监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。

<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定义的对象中的属性,newValueoldValue 都是新值,因为它们是同一个对象。

  • 若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。

代码:
使用ref定义对象类型数据:

<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定义对象类型数据

<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>

情况四 监视refreactive定义的【对象类型】数据中的**某个属性*

监视refreactive定义的【对象类型】数据中的某个属性,注意点如下:

  1. 若该属性值不是【对象类型】,需要写成函数形式。
    在这里插入图片描述

代码:

<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属性,触发了监控中的输出
在这里插入图片描述

  1. 若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数(这种的)
    验证代码:
<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>

结果:

写法一:当写法是:

watch(()=>person.car,(newVal,oldVal)=>{
    console.log('person.car变化了',newVal,oldVal);
},{deep:true})

效果: 此时修改单个属性会被watch监视到,修改整个对象不会引起,

写法二、当写法是 : 监控的内容写成了对象的形式,此时函数返回的是地址,

watch(()=>{return person.car},(newVal,oldVal)=>{
    console.log('person.car变化了',newVal,oldVal);
})

效果: 此时修改单个属性不会被watch监控到,修改整个person.car对象,也就是地址变化才会被watch监视到。

写法三、当写法是:
相交于第二种写法,加了一个watch的参数,此时就既能监控到其中每个属性的变化,又能监控到整体的变化了。

watch(()=>{return person.car},(newVal,oldVal)=>{
    console.log('person.car变化了',newVal,oldVal);
},{deep:true})

效果: 单个属性和对象整体的变化都能引起watch函数的执行。

_结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。

* 情况五

监视上述的多个数据

<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定义的对象,或者由上面形成的数组

http://www.kler.cn/news/356758.html

相关文章:

  • 【整合包及教程】第二代GPT-SoVITS V2:革新声音克隆技术
  • Linux——K8S平台的权限规划
  • connect 的断线重连设计
  • .cwsp勒索病毒:了解最新变种,以及如何保护您的数据
  • ubuntu24.0离线安装Ollama和纯cpu版本以及对接Spring AI
  • Missing classes detected while running R8报错解决方案
  • 博客|基于springBoot的精简博客系统设计与实现(附项目源码+论文+数据库)
  • [机器视觉]basler相机使用SN编号打开相机和采集
  • Android中的MVP模式
  • 【LeetCode】每日一题 2024_10_16 最小元素和最大元素的最小平均值(排序、模拟)
  • Android 开发 TabLayout 自定义指示器长度
  • 深入学习二叉树(BinaryTree)(纯小白进)
  • SpringBoot智能推荐:健康生活新体验
  • Lua表(Table)
  • MySQL程序介绍<一>
  • 侏罗纪公园不再是电影了吗?
  • 快速了解K8S几种网络实现
  • 代码复现(五):GCPANet
  • 高数导数积分知识点归纳
  • 使用Javascript实现一个Cron表达式的函数