vue开发中用vshow有时候没有效果的问题

我们公司同事这次开发一个项目,在页面上写了一个展开和折叠按钮,意图是对展示数据的不同情况做一个样式区别,通过点击图标可以打开或者折叠部分内容,经过测试同学测试发现有些情况下展开或者折叠按钮无反应!


vue开发中用v-if和v-show有时候没有效果的问题

于是我停下别的任务,打开前端代码,仔细阅读了起来。发现前端同学的代码是这样写的:


vue开发中用v-if和v-show有时候没有效果的问题

其实是很经典的写法,通过“v-if"标签来决定是显示展开”按钮“还是”折叠“按钮,同时会折叠对应的内容。

这段代码初略一看,没有发现什么问题,感到好奇的我就开始动手调试,在响应事件里面添加console输出元素状态。发现点击事件确实会触发,数组中的对应元素的字段也会变化,


vue开发中用v-if和v-show有时候没有效果的问题

通过观察控制台输出,发现点击事件确实有效,控制显示的字段确实被改变了。但是奇怪的是界面上的元素并没有变化,仔细看输出也是同一个按钮的输出。


vue开发中用v-if和v-show有时候没有效果的问题

这个问题一下子就难住我了,我本身是个后端,对前端代码并无研究,这次也是救急来改一下前端代码,因为前端兄弟早就不耐烦甲方改来改去了,情绪很大,就不方便老是麻烦人家。

以我浅薄的对vue的了解,觉得这样的操作应该是对的,但是为什么就不渲染到dom上呢,抱着不懂就问的心态,我开始打开搜索引擎搜索相关问题。当我提炼出这个问题的关键词”vue 数组元素变化,dom元素并不会改变“后,搜到了一片文章,一下子让我茅塞顿开!


vue开发中用v-if和v-show有时候没有效果的问题

一下子明白了为什么不显示效果了,按照文章中的说法,vue使用数组中的元素绑定v-show会遇到失效的问题,即绑定v-show的值已经改变,但是无法反映到dom上面,此时应该改为使用this.$set(this.showLoading,index,false)进行赋值.

但是另外一个想法又占据了我的头脑,为什么会这样呢?于是继续搜索this.$set()。。。

原来踩过这个坑的兄弟们不少,也已经写过很多这样的文章,如下面这位:

在vue开发中,常常会遇到这样的问题:当咱们给响应式的对象新增属性时,新增的属性并不会显示到页面中;一样的对于响应式的数组,增长元素、修改数组长度时,数组的这些变化也不会反映到页面中(响应式对象和响应式数组是指在vue初始化时期,利用Object.defineProperty()方法对其进行监听,这样在修改数据时会及时体如今页面上)

从上面例子中能够看出在页面加载后,咱们经过this.obj.b新增属性b时,页面中并无将属性b显示出来;经过vm.$data.obj.c新增属性c时,页面中也没有将属性c显示出来;可是经过打印对象obj,能够看出obj上存在属性b和c,为何呢?vue

这是因为对象obj及其属性a在vue初始化时已处理成响应式的,即当咱们改变对象obj的值或属性a的值时,会触发其在页面上的更新,可是当页面加载完成后,新增的属性b和c就不是响应式的,虽然经过打印this.obj能够看出对象obj上确实增长了属性b和c,可是因为b和c不是响应式的,因此新增的属性不会体如今页面上。react

对于数组arr也存在相似的问题,当咱们经过索引值添加元素或更改数组长度时,数组自己是发生变化了,可是没有及时体如今页面上。git

对于上述问题,咱们一般使用vue中的this.$set()来解决,那么this.$set()的原理是什么呢?github

在使用this.$set(target, key, value)时,target为须要添加属性的对象,key是要添加的属性名,value为属性key对应的值。

一、若是是在开发环境,且target未定义(为null、undefined)或target为基础数据类型(string、boolean、number、symbol)时,抛出告警;svg

二、若是target为数组且key为有效的数组key时,将数组的长度设置为target.length和key中的最大的那一个,而后调用数组的splice方法(vue中重写的splice方法)添加元素;this

三、若是属性key存在于target对象中且key不是Object.prototype上的属性时,代表这是在修改target对象属性key的值(无论target对象是不是响应式的,只要key存在于target对象中,就执行这一步逻辑),此时就直接将value直接赋值给target[key];

四、判断target,当target为vue实例或根数据data对象时,在开发环境下抛错;

五、当一个数据为响应式时,vue会给该数据添加一个__ob__属性,所以能够经过判断target对象是否存在__ob__属性来判断target是不是响应式数据,当target是非响应式数据时,咱们就按照普通对象添加属性的方式来处理;当target对象是响应式数据时,咱们将target的属性key也设置为响应式并手动触发通知其属性值的更新;

上面代码中最重要的就是以下代码:

defineReactive(ob.value, key, val)
ob.dep.notify()

这两行是将新增属性设置为响应式,并手动触发通知该属性值的更新,这就是经过this.$set()设置以后新增的属性会变成响应式并及时体如今页面中的缘由。

这位仁兄的解释是比较详细的,至于深入vue内部仔细研究更好的方法,超出了我们的学习能力范围,因此就先放下了。

一下子圆满解决了这个需求,虽然客户觉得理所当然,但是我自己感觉还是挺有成就感的,毕竟从后端过来研究一下前端的细节,也挺有意思的。

希望客户这个项目能跑成功!

展开阅读全文

页面更新:2024-03-18

标签:数组   中用   按钮   属性   元素   确实   对象   效果   代码   页面   发现   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top