vue2为啥只重写了7个数组方法?

1,221 阅读1分钟

首先看源码

const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
  // cache original method
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator (...args) {
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // notify change
    ob.dep.notify()
    return result
  })
})

确实只有7个方法被重写,至于为啥是7个,我观察了一下特征,这7个方法都是能改变数组本身的方法,突然顿悟也只有这个数组本身改变需要检测才需要去重新通知。接着我去MDN查了下,能改变数组本身分方法的还有以下这两个方法

Array.prototype.fill()
Array.prototype.copyWithin()

那为啥vue没有重写这两个方法呢,后来想了下,vue2出生的早,这两个方法es6出生的晚,那时候还不知道兼容这两个方法,我又想不会吧,那现在vue2给一个数组用fill方法,不就监听不到变化?于是我用代码试了下

 data() {
    return {
      arr: [1, 2, 4]
        }
 test() {
      this.arr.fill(0, 0, 2);
    },

<el-button @click="test"></el-button>

<div v-for="(item, i) in arr" :key="i"> {{ item }} </div>

果然点了没反应,数组不会重新渲染。

我想尤大肯定知道这个情况,人家就是不愿意改了,觉得没必要兼容,就算你提issue估计也不会改,我想了下一个hack的办法,arr.fill(0, 0, 2)完后再手动调用arr.push(),注意这里push一个空元素,也不会改变数组本身,但是因为vue会监听push方法,所以这才数组就会重新渲染。

结论:vue2是旧时代的产物了,能上3就上3吧,3里面这种问题就不复存在。