找回密码
 立即注册
首页 业界区 业界 vue3中的watch详细讲解保证看的明明白白

vue3中的watch详细讲解保证看的明明白白

毋献仪 昨天 07:58
1.png

Vue3 中的 watch 只能监视以下四种数据

1,ref 定义的数据。
2,一个响应式对象(如:reactive 定义的数据)。
3,函数的返回一个值(getter函数)。getter函数其实就是:能返回一个值的函数
4,由以上类型的值组成的数组
地址:https://cn.vuejs.org/api/reactivity-core.html#watch
2.png

vue3中watch监听 ref定义的基本数据类型
  1. <template>
  2.   
  3.    姓 <input v-model="xingValue" />
  4.      <button @click="changeHandler">更改值</button>
  5.   
  6. </template>
复制代码
3.png

watch监听ref声明的数据,第1个参数是不需要点value

如果我们使用watch监听ref声明的数据,第1个参数是不需要点value的。
  1. const age = ref(1);
  2. // watch监听ref声明的数据,第1个参数是不需要点value
  3. watch(age, (newValue,oldValue)=>{
  4.   console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
  5. })
复制代码
如果你使用ref声明的数据,如果你使用了点value。那么会报错的哈。
4.png

watch监听ref定义的对象数据类型

watch监听ref定义的【对象】数据类型时,监听的是对象的地址。
若是想要监听【对象内部属】性的变化,也就是细枝末节的变化。首要手动开启deep:true。
若是不开启deep:true,则监听不到。
watch监听ref定义的【对象】数据类型时,若是不开启deep:true,则监听不到对象内部属性的变化。
  1. <template>
  2.   
  3.      <p>{{ perosn }}</p>
  4.      <button @click="changeHandler">更改值</button>
  5.   
  6. </template>
复制代码
为啥更改ref定义的【对象】的属性时不会触发。
因为:watch监听ref定义的【对象】数据类型时,监听的是对象的地址。
地址没有发生改变,因此就不会触发。
5.png

如果想要:地址不发生改变时,也触发 ,需要开启:deep:true
watch开启deep:true监听ref对象内部属性的变化
watch开启deep:true监听ref对象内部属性的变化
  1. <template>
  2.   
  3.      <p>{{ perosn }}</p>
  4.      <button @click="changeHandler">更改值</button>
  5.   
  6. </template>
复制代码
6.png

watch监听ref定义的对象内部属性变化时,开启deep:true 新值和旧值是一样的

7.png

因为:watch监听ref定义的【对象】数据类型时,监听的是对象的地址。他们的地址是没有发生改变的。
watch监听ref定义的对象时,修改整个对象,newValue 和 oldValue 是不一样的
  1. <template>
  2.   
  3.      <p>{{ perosn }}</p>
  4.     <button @click="allHandler">更改整个属性</button>
  5.   
  6. </template>
复制代码
8.png

总结:watch监听ref声明对象类型的数据时

watch监视 ref 定义的【对象类型】数据时,直接写数据名,监视的是对象的【地址值】
若想监视对象内部的数据,要手动开启深度监视
若修改的是 ref 定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
若修改整个ref 定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了
9.png

watch监视【reactive】定义的【对象类型数据】,默认是开启深度监视的

只要我们使用watch去监听reactive定义的对象类型数据
无论数据层级有多么深,watch都是可以监听到的,并且它默认是开启了深度监听的。
无论内部变化的是某个属性,还是对象,都可以监听到。
监听这种是最省心的,因为无论怎么变化,都是可以监听到的哈哈。
  1. <template>
  2.   
  3.     <h1>{{  person }}</h1>
  4.     <button @click="allHandler">更改car这个对象</button>
  5.     <button @click="oneNameHandler">更改某个属性name</button>   
  6.   
  7. </template>
复制代码
10.png

有的文章会说:这种深度监听你是无法通过deep:false来进行关闭的。
这种说法不太正确,在现在的vue3.5版本中。
通过deep:false是可以关闭监听的。
  1. <template>
  2.   
  3.      <p>{{ person }}</p>
  4.     <button @click="allHandler">更改整个属性</button>
  5.   
  6. </template>
复制代码
11.png

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

watch监视 ref 或 reactive定义的【对象类型】数据中的某个属性,注意点如下:
1,若该属性值是【对象类型】,可直接写数据源,也可写成函数(建议写成函数)。并且推荐开启深度监听。
2,若该属性值不是【对象类型】,需要写成函数形式。否则会在控制台产生告警。
若该属性值不是【对象类型】,需要写成函数形式
  1. <template>
  2.   
  3.      <p>{{ person }}</p>
  4.     <button @click="allHandler">更改整个属性</button>
  5.   
  6. </template>
复制代码
12.png
  1. const person = ref({
  2.   age:18,
  3.   name:'张三',
  4.   car:{
  5.     c1:'电动车',
  6.     c2:'燃油车'
  7.   }
  8. });
  9. watch(person.value.name, (newValue,oldValue)=>{
  10.   console.log('newValue', newValue)
  11.   console.log('oldValue', oldValue)
  12. })
复制代码
13.png

现在有警告。为啥会警告。
因为:watch监视 ref 或 reactive定义的【对象类型】数据中的某个属性时。
如果这个属性值不是对象类型时,需要写成函数形式。【重点】
  1. // 因为这个属性值不是对象类型时,所以写成了函数形式
  2. watch(()=> person.age, (newValue,oldValue)=>{
  3.   console.log('新值:',newValue,'旧值:', oldValue)
  4. })
复制代码
14.png

watch监听reactive定义的对象,监听的属性是对象(写成数据源形式),你替换整个对象,监听不到。
  1. <template>
  2.   
  3.      <p>{{ person }}</p>
  4.       <button @click="allOneHandler">更改某个属性</button>
  5.       <button @click="allHandler">更改整个对象</button>
  6.   
  7. </template>
复制代码
15.png

为什么上面的直接更改整个监听对象,监听不到。
  1. person.car = {
  2.   c1:'--电动车--',
  3.   c2:'--燃油车--'
  4. }
  5. watch(person.car,()=>{})
复制代码
因为:当你替换整个car的时候,已经不再是原来的car。因此无法监听到。
怎么让它也可以监听到呢?写成函数形式。
  1. const person = reactive({
  2.   age:18,
  3.   name:'张三',
  4.   car:{
  5.     c1:'电动车',
  6.     c2:'燃油车'
  7.   }
  8. });
  9. function allHandler(){
  10.   person.car = {
  11.     c1:'--电动车--',
  12.     c2:'--燃油车--'
  13.   }
  14. }
  15. watch(()=>person.car, (newValue,oldValue)=>{
  16.   console.log('新值:',newValue,'旧值:', oldValue)
  17. })
复制代码
16.png

写成函数形式,监听整某个具体属性又不行了。
  1. <template>
  2.   
  3.     <h1>{{  person }}</h1>
  4.     <button @click="allHandler">更改car这个对象</button>
  5.     <button @click="allOneHandler">更改某个属性</button>
  6.    
  7.   
  8. </template>
复制代码
17.png

终极的解决办法
  1. const person = reactive({
  2.   age:18,
  3.   name:'张三',
  4.   car:{
  5.     c1:'电动车',
  6.     c2:'燃油车'
  7.   }
  8. });
  9. function allOneHandler(){
  10.   person.car.c1 += '--我的电动车--';
  11. }
  12. function allHandler(){
  13.   person.car = {
  14.     c1:'--电动车--',
  15.     c2:'--燃油车--'
  16.   }
  17. }
  18. watch(()=>person.car, (newValue,oldValue)=>{
  19.   console.log('新值:',newValue,'旧值:', oldValue)
  20. },{ deep: true })
复制代码
18.png

这样无论是更改整个对象还是对象内部的属性变化。都可以监听到啦。
总结:watch监听reactive/ref定义的内部属性时,监听的属性是对象,推荐写成函数形式,并且开启深度监听。
watch的数据源写成一个数组

有些时候,我们需要监听一个对象中的几个属性或者好几个不同的对象。
这个时候我们可以写成一个数组的形式
  1. <template>
  2.   
  3.     <h1>{{  person }}</h1>
  4.     <button @click="allHandler">更改car这个对象</button>
  5.     <button @click="oneNameHandler">更改某个属性name</button>   
  6.   
  7. </template>
复制代码
19.png

什么时候需要深度监听?

明明人家监听的是地址的变化,结果你想要监听某个值的变化
再次说明:watch为啥新值和旧值一样?

因为监听的是地址,你更改属性时,地址没有发生变化。
Object.assign更改时,也是只更改了属性,并没有产生新的地址。
相当于你新装修房子,你只换了灯,床,房子的地址没有发生变化。
因此:新值和旧值是一样的。
取消watch监听

将watch赋值给一个变量,调用这个变量。就可以停止监听了。
  1. import {  ref, computed, watch } from 'vue';
  2. const age = ref(1);
  3. function changeHandler(){
  4.   age.value +=1
  5. }
  6. let stopWatch =  watch(age, (newValue,oldValue)=>{
  7.   console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
  8.   if(newValue>3){
  9.     stopWatch()
  10.   }
  11. })
  12. </script>
复制代码
20.png

                                                                                                                               
21.jpeg
                                                微信                                                                                                本文版权归作者所有,欢迎转载,未经作者同意须保留此段声明,在文章页面明显位置给出原文连接
                        如果文中有什么错误,欢迎指出。以免更多的人被误导。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册