vue对于常用数组方法重写的原因和源码的学习

745 阅读1分钟
  • 原因:Obejet.defineproperty无法监听到数组和对象的内部的变化,所以vue2.0重写了常用的数组的方法来使得数组更新的时候触发页面的更新,对象的更新则使用this.$set,使得对象更新的时候触发页面的更新
  • vue2重写了哪些数组方法
var methodsToPatch = [
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sort',
    'reverse'
  ];
如果使用这7种以外的数组方法实现数据和视图同时更新则使用this.$set来实现更新
  • 重写数组的方法:
  var arrayProto = Array.prototype;
  var arrayMethods = Object.create(arrayProto);
  //arrayProto用来存储原生js的数组方法,用于接下来的遍历,
  //arrayMethods定义一个空对象用来存放vue重写的数组方法以避免污染Array.prototype上的数组方法。
    /**
   * Intercept mutating methods and emit events
   */
  methodsToPatch.forEach(function (method) {
    // cache original method
    var original = arrayProto[method];
    def(arrayMethods, method, function mutator () {
      var args = [], len = arguments.length;
      while ( len-- ) args[ len ] = arguments[ len ];

      var result = original.apply(this, args);
      var ob = this.__ob__;
      var 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
    });
  });
  
  由上述代码可见,由于push、unshift、splice会让数组索引发生改变,所以需要手动触发
  observer,这里的方法是定义一个inserted来控制是否触发响应式更新,如果为true,则
  用`ob.observeArray(inserted);`来手动给新插入的值设置响应式监听,再用
  `ob.dep.notify()`通知依赖更新,最后返回原生数组方法处理后的值` return result`

链接:vue对于常用数组方法重写的原因和源码的学习(vue面试必会知识点) - 起源地 (qiyuandi.com)