Vue数据更新视图未更新的多种情况以及解决办法

2,701 阅读3分钟

参考文章:www.jb51.net/article/256…

数据更新视图未更新的多种情况:

  1. 变量未在data里面定义初始化,不能检测该变量的变化,无法更新视图
  2. vue不能检测data中对象的动态添加和删除
  3. 数组
  4. 异步获取接口数据,DOM数据不发生变化
  5. 循环嵌套层级太深,视图未更新
  6. 路由参数变化时,页面不更新(数据不更新)

解决方案

  1. 变量未在data里面定义初始化,不能检测该变量的变化,无法更新视图;

    原因:vue2的数据响应式原理,变量必须在data对象上存在才能转化为响应式的。

    解决办法:将变量定义在data里

  2. vue不能检测data中对象的动态添加和删除

    例:

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

    解决:

    //可以使用set方法、assign方法
    //Vue.set
    Vue.set(this.obj, 'name', 'hello')
    //this.$set
    this.$set(this.obj, 'name', 'hello')
    //Object.assign()
    this.obj = Object.assign({}, this.obj, {name: 'hello'})
    //Vue.delete
    Vue.delete(this.obj, 'name')
    //this.$delete
    this.$delete(this.obj, 'name')
    
  3. 数组

    不能通过索引直接修改或者赋值,也不能修改数组的长度

    例:

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

    解决:

    //Vue.set
    Vue.set(this.list, 4, 'd')
    //this.$set
    this.$set(this.list, 4, 'd')
    //Array.prototype.splice
    this.list.splice(4, 4, 'd')
    //修改长度
    this.list.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' // 文字颜色变成红色
    })
    //也可以等数据获取完成后再触发dom更新
    
  5. 循环嵌套层级太深,视图不更新

    当嵌套太深时,视图不更新,可以使用深拷贝或者强制刷新

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

    拓展一个因为路由参数变化,而导致页面不更新的问题,页面不更新本质上就是数据没有更新。

    原因:路由视图组件引用了相同组件时,当路由参数变化时,会导致该组件无法更新

    解决办法:

    1、通过watch监听$route的变化

    2、给<router-view>绑定key属性,这样就会被认为不同的<router-view>