一篇文章搞懂Vue3中的watch

#前端实习

前言:

最近感觉自己的工作学习进展还是比较慢,今天主要写的是Vue3中的watch的相关方法,呃啊,拖延症很严重啊啊,希望自己能早日该掉,要是哪天在白天更新,和不再每日感叹自己的拖延症那一天大概就是自己的拖延症克服的那一天吧,如果有啥希望能看到的或者错误的希望可以指出,接下来速速进入正文


Vue3-watch 侦听器

基础概念:

在Vue3中,watch的特性进行了一些的改变和优化,与computed不同的是,watch常常用于监听响应式数据的变化,并且执行一些相关的从操作。比如,发送网络请求,更新DOM操作等。

功能:

监视数据的变化去做对应的事情

监视数据走逻辑

watch可以监视四种东西

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

基本语法:

watch(source, callback, options?)

遇到的相关情况

情况一

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

监视的适合不需要写.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++
}

//监视
const stopWatch = watch(sum,(newVal,oldVal)=>{
  console.log('sum发生了变化',newVal,oldVal);
  if(newVal > 10){
    console.log('sum大于10了')
    stopWatch()
  }
})

</script>

<style scoped>
.person{
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius:10px;
  padding: 20px;
}

button{
  margin-right: 10px;
} 
li{
  font-size: 30px;
}
</style>
情况二

监视ref定义的对象类型的数据,直接写数据名,监视的是对象的地址值,,如果想监视对象内部的数据,要手动开启深度监视

<template>
  <div class="person">
    <h1>情况二:监视【ref】定义的【对象类型】数据</h1>
    <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 { 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】定义的【对象类型】数据,监视的是对象的地址值。如果想要监视对象的属性,需要使用watchEffect
// watch的第一个参数是:被监视的数据
// watch第二个参数是:监视的回调
// watch的第三个参数是:配置对象(deep、immediate等等……) immediate表示是否立即执行回调
watch(person,(Value)=>{
  console.log('person发生了变化',Value);
  },{deep:true,immediate:true})
</script>

<style scoped>
.person{
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius:10px;
  padding: 20px;
}

button{
  margin-right: 10px;
} 
li{
  font-size: 30px;
}
</style>

注意:

  1. 如果修改的是ref定义的对象中的属性,newValue和oldValue都是新值,因为他们是同一个对象
  2. 如果修改整个ref定义的对象,newValue是新值,oldValue是旧值,因为不是同一个对象了
情况三

监视reactive定义的对象类型选的数据,且默认开启了深度监视

<template>
  <div class="person">
    <h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
    <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,watch } from 'vue';

//数据
let person = reactive({
  name: '张三',
  age: 18
})

//方法
function changeName(){
  person.name += '~'
}

function changeAge(){
  person.age += 1
}

function changePerson(){
  Object.assign(person , {
    name: '李四',
    age: 90
  })  //批量地将所有可枚举属性的值从一个或多个源对象分配到目标对象
}

// //监视 情况三、监视【reactive】定义的【对象类型】数据,且默认是开启深度监听的,该深度监听是递归的且无法关闭
watch(person,(newValue,oldValue)=>{
  console.log('person发生了变化',newValue,oldValue); //因为地址没有变化所以oldValue和newValue是一样的
  })
</script>

<style scoped>
.person{
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius:10px;
  padding: 20px;
}

button{
  margin-right: 10px;
} 
li{
  font-size: 30px;
}
</style>
情况四

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

<template>
  <div class="person">
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <h2>车: {{ person.car.brand }} 价值: {{ person.car.price }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeBrand">修改车的品牌</button>
    <button @click="changePrice">修改车的价值</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:{
    brand: '宝马',
    price: 1000000
  }
  })

  //方法
function changeName (){
  person.name += '~'
}
function changeAge (){
  person.age += 1
}
function changeBrand (){
  person.car.brand += '~'
}
function changePrice (){ 
  person.car.price += 100000
}
function changeCar (){
  person.car = {
    brand: '奥迪',
    price: 2000000
  }
}

//监视 情况四:监视:监视响应式对象的某个属性,而且该属性是基本类型的,要写成函数式
watch(()=>{return person.name},(value)=>{
  console.log('person发生了变化',value);
})

//监视 情况四: 监视:监视响应式对象的某个属性,而且该属性是对象类型的,要写成函数式,也可以直接写,但是不太推荐有时候容易出问题
watch(()=>person.car,(value)=>{
  console.log('person.car发生了变化',value);
},{deep:true})  //外面一包函数,就又只监听地址了,所以要加deep:true

// watch(person.car,(value)=>{
//   console.log('person.car发生了变化',value);
// }) //这样一但car整个发生变化,地址改变,这样就不会监听到了
</script>

<style scoped>
.person{
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius:10px;
  padding: 20px;
}

button{
  margin-right: 10px;
} 
li{
  font-size: 30px;
}
</style>

注意点如下:
该属性不是【对象类型】,需要写成函数形式

该属性依然是【对象类型】,可直接编,也可直接写成函数,不过建议要写成函数

结论:监视的如果是对象里的属性,请最好谢谢函数式子。

注意点,如果对象监视的是地址值,需要关注对象的内部的相关信息,需要手动开启深度监视

情况五

监视:监视上述的多个数据

使用数组把要监视的属性全都括起来

<template>
  <div class="person">
    <h1>情况五:监视上述的多个数据</h1>
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <h2>车: {{ person.car.brand }} 价值: {{ person.car.price }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeBrand">修改车的品牌</button>
    <button @click="changePrice">修改车的价值</button>
    <button @click="changeCar">修改整个车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
import { reactive , toValue, watch} from 'vue';
//数据
let person = reactive({
  name: '海星',
  age: 18,
  car:{
    brand: '宝马',
    price: 1000000
  }
  })
5
  //方法
function changeName (){
  person.name += '~'
}
function changeAge (){
  person.age += 1
}
function changeBrand (){
  person.car.brand += '~'
}
function changePrice (){ 
  person.car.price += 100000
}
function changeCar (){
  person.car = {
    brand: '奥迪',
    price: 2000000
  }
}
//监视 情况五:监视:监视上述的多个数据
watch(()=>[person.car.brand,person.name],(Value)=>{
  console.log('person.car.brand或者person.name发生了变化',Value)}
)


</script>

<style scoped>
.person{
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius:10px;
  padding: 20px;
}

button{
  margin-right: 10px;
} 
li{
  font-size: 30px;
}
</style>

以上的情况一和情况四用的比较多,写函数比较稳定,我不管你是什么我反手就写一个函数,需要深度,那咱就deep: true

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值