ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

踩坑不断的watch

2021-08-20 15:29:44  阅读:167  来源: 互联网

标签:oldV 不断 ref watch reactive newV 监听


watch

今天看教程,发现vue3里面的watch坑超级多,特此记录下。

语法

vue3组件改为组合式组件,所需的配置大都需要自己去引入,watch也是如此。

watch(attr, callBack(newV, oldV), obj)

vue3将计算属性(computed),侦听属性(watch)等一些配置设计为了函数模式,使用的时候直接调用watch函数即可(前提是已经引入)。attr表示需要监听的数据,callBack则为需要处理的回调函数,参数同vue2一样,newV为改变后的数据,oldV为改变前的数据。obj为一个配置对象,可以配置vue2的deep,immediate属性。

不同使用情况不同分析

1.监听ref所定义一个响应式数据

let username = ref('fufu')
watch(username, (newV, oldV) => {
  console.log(newV, oldV);  //fufu~  fufu
})

修改给username 添加 ‘~’,触发侦听。值得庆幸的是这是vue3里面少有的没有坑的情况之一!

2.同时监听多个ref所定义一个响应式数据

在实际项目里,我们肯定会有监听多个数据的需求,在vue3里面,watch配置项已经可以多次使用,也就是说,想要监听多个数据,可以如下:

let username = ref('fufu')
let height = ref(170)
watch(username, (newV, oldV) => {
  console.log(newV, oldV);  //fufu~  fufu
})
watch(height , (newV, oldV) => {
  console.log(newV, oldV);  //171 170
})

但是这样写明显会造成大量的代码重复,vue3其实也支持在watch配置函数里面的第一个参数的位置放数组。

let username = ref('fufu')
let height = ref(170)
watch([username, height ], (newV, oldV) => {
  console.log(newV, oldV); 
})

当两个值都改变时,回调函数里面的新老值都会变成一个数组。
如fufu改成fufu~,170改成171的话,newV, oldV值为[‘fufu~’, 171], [‘fufu’, 170]

3.监听一个reactive所定义一个响应式数据(值为简单类型)

let person = reactive({
  age: 20,
  wages: 20
})
watch(person, (newV, oldV) => {
  console.log(newV, oldV);  
})

当我们将age加1的时候,打印出在这里插入图片描述
第一个坑出现了!!!我们惊奇的发现,它打印的oldV和newV竟然是一样的!!! 这并非我们代码的问题,是vue3本就存在的,无法解决。可能有人会想到既然reactive无法被监听,那我们使用ref定义对象不就行了?

let person = ref({
  age: 20,
  wages: 20
})
watch(person.value, (newV, oldV) => {
  console.log(newV, oldV);  
})

经过测试发现,其实结果是一样的。其实很好理解,ref方法定义一个对象时,也是去求助的reactive这个方法,说到底,定义对象用的都是reactive,并无区别。

还有人可能会提问说为什么这个时候监听需要.value,而之前不需要呢?这里就要提下watch监听的到底是什么?当监听一个ref定义的响应式对象时,不会开启自动深层次监听,而使用.vlaue就相当于是监听的reactive定义的响应对象,是会强制监听的。当然,我们也可以不写.value,而是在第三个参数里面配置下deep属性,同样可以实现。

并且坑远不止如此!!!
第二个坑出现了!!!

let demo = reactive({
  a: {
    b: {
      c: 10
    }
  }
})
watch(demo, (newV, oldV) => {
 console.log(newV, oldV, person)
})

当我们改变demo里面的c属性时,发现还是会变监听到。难道是默认开启深度监听?这里就不进行测试了,其实这就是一个坑,即使你在watch的第三个参数里面配置deep为false,他还是会被监听到。

那么我们永远拿不到正确的oldV值了嘛?
其实在日常开发中,oldV值我们用的是很少的,但是也不乏还是有需求需要,所以我们可以将需要监听的值转换为简单类型。

let age = ref(20)
let wages = ref(20)
watch(age , (newV, oldV) => {
  console.log(newV, oldV);  
})
watch(wages , (newV, oldV) => {
  console.log(newV, oldV);  
})

这是最笨的方法了,不推荐!!!
其实还有一种办法,那就是监听对象的属性,也就是情况四了

4.监听一个reactive所定义一个响应式数据的一个属性

let person = reactive({
  age: 20,
   wages: 20
 })
watch(() => person.age, (newV, oldV) => {
  console.log(newV, oldV);
 })

当我们改变数据时,发现newV, oldV值可以正确获取。

5.监听一个reactive所定义多个响应式数据

有情况二就一定也会出现情况4啦。

let person = reactive({
  age: 20,
  wages: 20
 })
watch([() => person.age, () => person.wages], (newV, oldV) => {
  console.log(newV, oldV);
 })

这里的newV, oldV值也会变成一个数组对应监听的几个值。

6.监听一个reactive所定义的一个响应数据(值为对象)

let demo = reactive({
  a: {
    b: {
      c: 10
    }
  }
})
watch(() => demo.a, (newV, oldV) => {
 console.log(newV, oldV, person)
})

然后我们改变数据c时惊奇的发现…为啥没有被监听?代码错了?并不是,仔细想想其实是我们忘记了deep属性。这个时候有人要反对啊,情况三你说的deep属性默认就有,并且还控制不了,只能为true,这里怎么就又需要手动添加呢?你问我我只能说第三个坑出现了!!!

标签:oldV,不断,ref,watch,reactive,newV,监听
来源: https://blog.csdn.net/qq_44473483/article/details/119796494

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有