Vue的数据更新了但页面没有更新及数据频繁更新而页面只更新一次

1、Vue的数据更新了,而页面没有更新

由于Vue的数据双向绑定,我们只需要修改数据,页面就会自动更新。但有时我们修改了数据,页面却也没有更新,这是为什么?

以下用Vue2为例,整理常见的几种问题

1、所修改的数据根本不存在于data中

Vue在初始化实例时,会对data中的数据进行getter、setter,而如果变量不在data中,则不是响应式的

new Vue({
  data:{},
  template: '<div>{{message}}</div>'
})
this.message = 'Hello world !' // `message` 不是响应式的页面不会发生变化

解决: 保证这个数据是在data中的,是响应式数据

 new Vue({
  data: {
    message: '',
  },
  template: '<div>{{ message }}</div>'
})
this.message = 'Hello world!'

2、Vue无法监测到对象中属性的动态添加和删除

 new Vue({
  data:{
    obj: {
      id: 1
    }
  },
  template: '<div>{{ obj.message }}</div>'
})
this.obj.message = 'hello' // 不是响应式的
delete this.obj.id       // 不是响应式的

解决:

// 动态添加 - Vue.set
Vue.set(this.obj, 'id', 002)
 
// 动态添加 - this.$set
this.$set(this.obj, 'id', 002)
 
// 动态添加多个
// 代替 Object.assign(this.obj, { a: 1, b: 2 })
this.obj = Object.assign({}, this.obj, { a: 1, b: 2 })
 
// 动态移除 - Vue.delete
Vue.delete(this.obj, 'name')
 
// 动态移除 - this.$delete
this.$delete(this.obj, 'name')

3、对于数组,不能通过索引直接修改或赋值,也不能修改数组长度

new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
this.items[1] = 'x' // 不是响应性的
this.items[3] = 'd' // 不是响应性的
this.items.length = 2 // 不是响应性的

解决:在修改数组数据的时候,我们应该使用push(),pop(),shift(),unshift(),splice(),sort(),reverse()等原生的方法去操作数据,因为vue可以直接检测这些方法所带来的数组数据变化

// Vue.set
Vue.set(this.items, 4, 'd')
 
// this.$set
this.$set(this.items, 4, 'd)
 
// Array.prototype.splice
this.items.splice(indexOfItem, 4, 'd')
//修改长度
this.items.splice(3)

4、异步获取接口数据,DOM数据不发现变化

原因:Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

例如:

<div id="example">{{message}}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
vm.$el.style.color = 'red' // 页面没有变化

解决:

var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
//使用 Vue.nextTick(callback) callback 将在 DOM 更新完成后被调用
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
  vm.$el.style.color = 'red' // 文字颜色变成红色
})

5、循环嵌套层级太深,视图不更新

可以采用页面强制刷新 this.$forceUpdate() ,但不是很建议

或者能不能尝试给这个循环嵌套数据的外层组件或页面添加v-if,设置一个变量控制其显示与隐藏,在调用接口或者是要修改这个循环嵌套的数据后,切换控制v-if的变量true和false,就相当于重新渲染了一次

6、路由参数变化时,页面不更新(数据不更新)

原因:路由视图组件引用了相同组件时,当路由参数变化时,会导致该组件无法更新,也就是常说的页面无法更新问题

2、Vue的数据频繁变化,但是页面只更新一次

其实就是上面的第四点

原因:Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值