注意:
在一个组件实例中,只有在data里初始化的数据才是响应的,Vue不能检测到对象属性的添加或删除,没有在data里声明的属性不是响应的。
Vue不允许在已经创建的实例上动态添加根级响应式属性,但是可以使用$set方法将相应属性添加到嵌套的对象上。
数组数据变动,使用某些方法操作数组,变动数据时,有些方法无法被vue监测
push()
,pop()
,shift()
,unshift()
,splice()
,sort()
,reverse()
可被vue检测到filter()
, concat()
, slice()
。这些不会改变原始数组,但总是返回一个新数组。当使用非变异(不改变原数组返回新数组)方法时,可以用新数组替换旧数组。
vue不能检测以下变动的数组:
1、当你利用索引直接设置一个项时,vm.items[indexOfItem] = newValue
2、当你修改数组的长度时,例如: vm.items.length = newLength
this.$forceUpdate() //强制刷新
解决第一类问题:可以通过
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice`
example1.items.splice(indexOfItem, 1, newValue)
第二类问题可以通过
example1.items.splice(newLength)
对象属性的添加或删除
由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
解决办法:
使用 Vue.set(object, key, value)
方法将响应属性添加到嵌套的对象上
Vue.set(vm.someObject, 'b', 2)
或者 this.$set(this.someObject,'b',2)
(这也是全局 Vue.set 方法的别名)
使用Object.assign()创建新对象,并且computed的属性依赖于data的属性,类似下面这种
data () { return { carts: this.$store.state.carts } }, computed: { getCarts() { for (let i = 0; i < this.carts.length; i++) { this.carts[i] = Object.assign({}, this.carts[i], { editState: false }); } this.carts = Object.assign({}, this.carts); return this.carts; } }
异步更新队列
在最新的项目中遇到了这种情况,数据第一次获取到了,也渲染了,但是第二次之后数据只有在再一次渲染页面的时候更新,并不能实时更新。
网上查了资料才知道,Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。
解决办法:
可在数据变化之后立即使用 Vue.nextTick(callback)
。这样回调函数在 DOM 更新完成后就会调用
总结
- 遇到问题先谷歌和百度
- 猜测哪里出了问题,去看官方文档原理
- vue数据变化视图没更新去看响应式原理,和数组变异原理。