Vue2更改数组和更改对象属性的底层原理 -- 源码剖析
数组
- 不能通过更改数组长度的方式去更改数组,这样也不会渲染页面。
- Vue的响应式是通过
Object.defineProperty()实现的,这个api 没办法监听数组长度的变化,也就没办法监听数组的新增。 - 解决方式:js
vm.items.splice(newLength)
- Vue的响应式是通过
- 不能通过数组的索引(下标)去更改数组的值,这样不会渲染页面。
- Vue无法检测通过数组索引改变数组的操作,这不是
Object.defineProperty()api的原因,而是尤大认为性能消耗与带来的用户体验不成正比。对数组进行响应式检测会带来很大的性能消耗,因为数组项可能会大,比如1000条、10000条。 - 解决方式:js
// Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue) //$set vm.$set(vm.items, indexOfItem, newValue) //$delete this.$delete(this.array[0],'hobby')
- Vue无法检测通过数组索引改变数组的操作,这不是
- 所以为了更友好的操作数组并触发响应式检测,Vue重写了对数组引起副作用(改变原数组)的7种方法。js
// 1.push() 向数组后面添加一个或多个元素 this.letters.push('e') this.letters.push('e', 'f') // 2.pop() 删除数组中的最后一个元素 this.letters.pop() // 3.shift() 删除数组中的第一个元素 this.letters.shift() // 4.unshift() 向数组前面添加一个或多个元素 this.letters.unshift('h') this.letters.unshift('h', 'k') // 5. splice() 删除 替换 插入 多个元素 // splice(0) 删除所有元素 相当于 arr.length=0 this.letters.splice(3, 0, 'k', 'f') // 6.sort() 排序 字母数字 this.letters.sort() // 7.reverse() 反转数组 this.letters.reverse()
对象
- 向对象内添加或者删除属性,不会渲染页面。
- 解决方式:js
Vue.set(Object, NewKey, NewValue) //全局方式 this.$set(this.Object, propertyName, NewValue) //实例方法
- 解决方式:
- 有时你可能需要为已有对象赋值多个新
property,比如使用Object.assign()或_.extend()。但是,这样添加到对象上的新property不会触发更新- 解决方式:js
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
- 解决方式:
- 无法用
delete myObject.Name来删除属性- 解决方式js
this.$delete( this.object, "要删除的属性key")
- 解决方式