Skip to content

Vue2更改数组和更改对象属性的底层原理 -- 源码剖析 ​

数组 ​

  1. 不能通过更改数组长度的方式去更改数组,这样也不会渲染页面。
    • Vue的响应式是通过Object.defineProperty()实现的,这个api 没办法监听数组长度的变化,也就没办法监听数组的新增。
    • 解决方式:
      js
        vm.items.splice(newLength)
  2. 不能通过数组的索引(下标)去更改数组的值,这样不会渲染页面。
    • 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')
  3. 所以为了更友好的操作数组并触发响应式检测,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()

对象 ​

  1. 向对象内添加或者删除属性,不会渲染页面。
    • 解决方式:
      js
        Vue.set(Object, NewKey, NewValue)  //全局方式  
        this.$set(this.Object, propertyName, NewValue)  //实例方法
  2. 有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新
    • 解决方式:
      js
        // 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
        this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
  3. 无法用delete myObject.Name来删除属性
    • 解决方式
      js
          this.$delete( this.object, "要删除的属性key")