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

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

🏡作者主页:点击!

🤖Vue专栏:点击!

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

文章目录

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

【watch】作用

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

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

  • 若修改整个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>

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

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

  1. 若该属性值不是 【对象类型】,需要写成函数形式。

代码:

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属性,触发了监控中的输出

  1. 若该属性值是依然 是【对象类型】,可直接编,也可写成函数,建议写成函数(这种的)
    验证代码:
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定义的对象,或者由上面形成的数组
相关推荐
四喜花露水27 分钟前
Vue 自定义icon组件封装SVG图标
前端·javascript·vue.js
程序员爱技术5 小时前
Vue 2 + JavaScript + vue-count-to 集成案例
前端·javascript·vue.js
cs_dn_Jie10 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic10 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿10 小时前
webWorker基本用法
前端·javascript·vue.js
customer0811 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
getaxiosluo12 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v12 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
栈老师不回家13 小时前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙13 小时前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js