vue3 - 04 - watch的使用

watch

  • [一、 watch 基础认识](#一、 watch 基础认识)
    • [1. 监视 ref 定义的【基本类型】数据](#1. 监视 ref 定义的【基本类型】数据)
    • [2. 监视 ref 定义的【对象类型】的数据](#2. 监视 ref 定义的【对象类型】的数据)
    • [3. 监视 reactive 定义的【对象类型】的数据](#3. 监视 reactive 定义的【对象类型】的数据)
    • [4. 监视 ref 或 reactive 定义的【对象类型】数据中的【某个属性】](#4. 监视 ref 或 reactive 定义的【对象类型】数据中的【某个属性】)
    • [5. 监视上诉的多个数据](#5. 监视上诉的多个数据)
  • 二、watchEffect

一、 watch 基础认识

watch作用: 监视数据的变化(和vue2中的watch作用一致)

特点: vue3 中的 watch 只能监视以下四种数据:

  1. ref 定义的数据
  2. reactive 定义的数据
  3. 函数返回一个值(getter 函数)
  4. 一个包含上诉内容的数据

1. 监视 ref 定义的【基本类型】数据

  • 直接写数据名即可,监视的是其 value 值的改变
  • 返回的 stopWatch 是一个回调函数,可以通过 stopWatch()停止监视

举例如下:

javascript 复制代码
<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>

2. 监视 ref 定义的【对象类型】的数据

  • 如果直接写数据名,监视的是对象的地址值
  • 如果想要监视对象内部的数据,要手动开启深度监视(deep:true)
  • 开启 immediate:true 后刚打开页面就会监视一次

关于浅拷贝和深拷贝:

  • 浅拷贝只复制了地址
  • 深拷贝是玩玩全全复制一份数据,但是地址不同

注意:

  • 如果修改的是 ref 定义的对象中的属性,则 newValue 和 oldValue 都是新值,因为他们是同一个对象
  • 如果修改的是 ref 定义的对象,newValue 是新值,oldValue 是旧值,因为不是同一个对象了

举例如下:

javascript 复制代码
<script lang="ts" setup name="Person">
  import {ref,watch} from 'vue'
  
  // 数据
  let person = ref({
    name:'张三',
    age:18
  })
  
  // 方法
  function changeName(){
    person.value.name += '~'
  }
  function changeAge(){
    person.value.age += 1
  }
  function changePerson(){
    person.value = {name:'李四',age:90}
  }


  /* 
    监视,情况二:监视【ref】定义的【对象类型】数据,监视的是对象的地址值,若想监视对象内部属性的变化,需要手动开启深度监视
    watch的第一个参数是:被监视的数据
    watch的第二个参数是:监视的回调
    watch的第三个参数是:配置对象(deep、immediate等等.....) 
  */
  watch(person,(newValue,oldValue)=>{
    console.log('person变化了',newValue,oldValue)
  },{deep:true, immediate: true})
  
</script>

3. 监视 reactive 定义的【对象类型】的数据

  • 监视 reactive 定义的对象类型的数据,默认会开启深度监视,而且无法关闭深度监视

举例如下:

javascript 复制代码
<script lang="ts" setup name="Person">
  import {reactive,watch} from 'vue'
  
  // 数据
  let person = reactive({
    name:'张三',
    age:18
  })
  let obj = reactive({
    a:{
      b:{
        c:666
      }
    }
  })
  
  // 方法
  function changeName(){
    person.name += '~'
  }
  function changeAge(){
    person.age += 1
  }
  function changePerson(){
    Object.assign(person,{name:'李四',age:80})
  }
  function test(){
    obj.a.b.c = 888
  }

  // 监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的
  watch(person,(newValue,oldValue)=>{
    console.log('person变化了',newValue,oldValue)
  })
  watch(obj,(newValue,oldValue)=>{
    console.log('Obj变化了',newValue,oldValue)
  })
</script>

4. 监视 ref 或 reactive 定义的【对象类型】数据中的【某个属性】

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

  1. 若该属性值不是【对象类型】,需要写成函数形式
  2. 若该属性值是依然是【对象类型】,可直接写,也可写成函数,建议写成函数

结论: 监视的要是对象里的属性,那么最好写函数式

举例如下:

javascript 复制代码
<template>
  <div class="box">
    <div>姓名:{{ person.name }}</div>
    <div>年龄:{{ person.age }}</div>
    <div>汽车1:{{ person.car.c1 }}</div>
    <div>汽车2:{{ person.car.c2 }}</div>
    <br>
    <button @click="changeName">改变姓名</button>
    <button @click="changeAge">改变年龄</button>
    <button @click="changeC1">改变汽车1</button>
    <button @click="changeC2">改变汽车2</button>
    <button @click="changeCar">改变所有车</button>
  </div>
</template>

<script lang="ts" setup name="Person111">
  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: '小电驴1', c2: '小电驴2'}
  }

  // 监视  情况四:监视【对象类型】的数据中的某个属性,该属性是基本类型
  watch(() => person.name, (newValue, oldValue) => {
    console.log('name发生变化了',newValue, oldValue)
  })

  // 监视  情况四:监视【对象类型】的数据中的某个属性,该属性是对象类型
  // 监视效果:只有car整个发生变化才能监视到,car.c1发生变化监视不到,如果想要car.c1也能监视到,就开启深度监视
  watch(() => person.car, (newValue, oldValue) => {
    console.log('person.car发生改变了',newValue, oldValue)
  }, { deep: true })

</script>

5. 监视上诉的多个数据

举例如下:

javascript 复制代码
<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>

二、watchEffect

  • 官网解释:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
  • watch 对比 watchEffect
    • 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
    • watch:要明确指出监视的数据
    • watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)

举例如下:

javascript 复制代码
<template>
  <div class="person">
    <h1>需求:水温达到50℃,或水位达到20cm,则联系服务器</h1>
    <h2 id="demo">水温:{{temp}}</h2>
    <h2>水位:{{height}}</h2>
    <button @click="changePrice">水温+1</button>
    <button @click="changeSum">水位+10</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import {ref,watch,watchEffect} from 'vue'
  
  // 数据
  let temp = ref(0)
  let height = ref(0)

  // 方法
  function changePrice(){
    temp.value += 10
  }
  function changeSum(){
    height.value += 1
  }

  // 用watch实现,需要明确的指出要监视:temp、height
  watch([temp,height],(value)=>{
    // 从value中获取最新的temp值、height值
    const [newTemp,newHeight] = value
    // 室温达到50℃,或水位达到20cm,立刻联系服务器
    if(newTemp >= 50 || newHeight >= 20){
      console.log('联系服务器')
    }
  })

  // 用watchEffect实现,不用
  const stopWtach = watchEffect(()=>{
    // 室温达到50℃,或水位达到20cm,立刻联系服务器
    if(temp.value >= 50 || height.value >= 20){
      console.log(document.getElementById('demo')?.innerText)
      console.log('联系服务器')
    }
    // 水温达到100,或水位达到50,取消监视
    if(temp.value === 100 || height.value === 50){
      console.log('清理了')
      stopWtach()
    }
  })
</script>
相关推荐
卸任11 小时前
Vibe coding工具使用心得
前端·ai编程
brien912 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance12 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M12 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写13 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李13 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易13 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding13 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马13 小时前
前沿视界
前端
kyriewen13 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员