参考文章:www.jb51.net/article/256…
数据更新视图未更新的多种情况:
- 变量未在data里面定义初始化,不能检测该变量的变化,无法更新视图
- vue不能检测data中对象的动态添加和删除
- 数组
- 异步获取接口数据,DOM数据不发生变化
- 循环嵌套层级太深,视图未更新
- 路由参数变化时,页面不更新(数据不更新)
解决方案
-
变量未在data里面定义初始化,不能检测该变量的变化,无法更新视图;
原因:vue2的数据响应式原理,变量必须在data对象上存在才能转化为响应式的。
解决办法:将变量定义在data里
-
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')
-
数组
不能通过索引直接修改或者赋值,也不能修改数组的长度
例:
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)
-
异步获取接口数据,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更新
-
循环嵌套层级太深,视图不更新
当嵌套太深时,视图不更新,可以使用深拷贝或者强制刷新
-
路由参数变化时,页面不更新(数据不更新)
拓展一个因为路由参数变化,而导致页面不更新的问题,页面不更新本质上就是数据没有更新。
原因:路由视图组件引用了相同组件时,当路由参数变化时,会导致该组件无法更新
解决办法:
1、通过watch监听$route的变化
2、给
<router-view>
绑定key属性,这样就会被认为不同的<router-view>