Vue数据更新了但是视图不更新

原文链接:《Vue数据更新了但是视图不更新》

最近在发生了一件很奇怪的事,明明Vue中data的数据已经更新了,但是页面渲染出来的内容并没有跟随着更新,包括使用elemeUI的时候也有这种情况!难道是数据双向绑定出问题了?

经过我东查查西找找,终于是找到了原因和解决方法,为了避免以后找不到,那就在这里记录一下吧!

可能出现的原因

通过集成各家所讲,本人简单罗列了可能是以下原因导致的,当然,每个人遇到的情况不一样,甚至还会遇到更加邪门的事情,还需要根据自己的实际情况去排查。

1. 数据响应性问题

Vue无法检测到对象属性的添加或删除。例如,如果添加了一个新的属性到已经存在的对象上,Vue将不会触发视图更新。

利用索引直接设置一个项时,例如 vm.items[indexOfItem] = newValue

数组数据变动,使用某些方法操作数组,变动数据时,有些方法无法被vue监测:

  • push()pop()splice()sort()reverse()可被vue检测到。
  • filter()concat()slice() 这些不会改变原始数组,但总是返回一个新数组。

2. 异步更新队列

Vue在更新DOM时是异步执行的。当数据变化时,Vue不会立即更新DOM,而是等到下一次事件循环再执行更新。如果需要立即更新视图,可以使用 Vue.nextTick(callback) 方法。

3. 使用v-if条件渲染

如果元素是通过 v-if 条件渲染的,并且条件在初始渲染时是 false ,当条件变为 true 时,元素可能不会立即出现。确保条件逻辑正确。

4. 缓存问题

如果使用了某些缓存机制,如 keep-alive ,那就得看看是不是有处理了组件的激活和停用状态。

开始排查

首先在控制台中打印出最后更新的数据,得出的结果是正确的,也就是说在js中并没有存在处理上的问题。

然后是使用简单粗暴的方法,先注释掉对应的页面标签,然后再放开注释,这个时候惊喜发现数据更新了!

这个时候就需要进一步去测试,所以我定义了一个变量为布尔值,在父级元素中使用 v-if 去绑定这个布尔值,然后再数据赋值之前将布尔值设置为 false,然后在数据赋值后将这个布尔值改成 true,使用 v-if 这个操作就实现了类似于刚才的注释操作。

这里补充一下,v-ifv-show 虽然在视觉上看是一样的效果,但是 v-if 是将对应的元素进行注释操作,简单直白的说就是销毁了这个元素,而 v-show 只是对该元素设置了CSS中的 display: none; 的属性,实际上这个元素还是存在在页面中。

其实到这一步已经解决了视图不更新的问题,但是感觉这样子操作并不优雅!因为在使用 v-if 的时候,虽然在浏览器上处理的很快,但有个问题就是再快也快不过眼睛,在频繁使用 v-if 操作的时候就会看到这个页面元素就跟天上的星星那样一闪一闪的。这显然对用户体验是非常不友好的。

所以就拿出了以下“法宝”!

this.$set()

this.$set 是 Vue.js 中的一个方法,用于解决Vue不能检测到对象属性的添加或删除的问题。当需要动态地向响应式对象添加一个属性,并确保这个新属性同样是响应式的(即当其值改变时,视图也会更新),可以使用 this.$set 方法。

在Vue2中,this.$set 的常见用法如下:

this.$set(target, propertyName, value)
  • target:要添加属性的对象。
  • propertyName:要添加的属性的名称(字符串形式)。
  • value:要设置的新属性值。

例如,当前有一个响应式对象obj,然后在此基础上添加一个名为newProp的新属性:

new Vue({
  data: {
    obj: {
      existingProp: 'some value'
    }
  },
  methods: {
    addNewProp() {
      this.$set(this.obj, 'newProp', 'newValue');
    }
  }
});

在调用 addNewProp 方法后,obj现在将包含一个名为 newProp 的新属性,且该属性是响应式的。如果直接通过 obj.newProp = 'newValue' 来添加属性,那么这个新属性将不会是响应式的。

而在Vue3中,this.$set 已被移除,因为Vue3使用了 Proxy 来实现响应式系统,这样在数据变化后能够更精确地检测到属性的添加和删除。

this.$forceUpdate()

this.$forceUpdate() 是 Vue.js 中的一个实例方法,用于强制Vue实例重新渲染页面。在Vue.js中,当组件或其数据发生变化时,Vue会自动检测这些变化并重新渲染页面。然而,在某些情况下,Vue可能无法检测到数据的变化,因此不会触发重新渲染,使用 this.$forceUpdate() 方法来手动触发重新渲染。

使用 this.$forceUpdate() 的步骤如下:

  • 在组件中定义需要更新的数据。
  • 在组件的方法中使用 this.$forceUpdate()。
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
      this.$forceUpdate();
    }
  }
};

但是!this.$forceUpdate() 应该是一种较少使用的方法,因为这个方法破坏了Vue.js的响应性系统。在大多数情况下,除非只有在Vue.js不能自动检测到数据变化并重新渲染的情况下,才应该使用 this.$forceUpdate()

讲到这里,基本上原因和处理方案都罗列的差不多了,这个时候只需要根据实际情况去选择对应的方法去处理。个人观点,无论是用哪种方法,首先考虑的还是用户体验,其次才是处理方法优化,完毕!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值