美文网首页
vue2.0的数组劫持

vue2.0的数组劫持

作者: Mr无愧于心 | 来源:发表于2019-12-02 14:49 被阅读0次

    Object.defineProperty不支持监听数组变化。所以需要重写数组上面的方法。

    vue2.0对数组的方法进行了劫持,重写了能改变数组的方法实现数据的更新

    const arrayProto = Array.prototype//原生Array的原型
    export const arrayMethods = Object.create(arrayProto);
    [
      'push',
      'pop',
      'shift',
      'unshift',
      'splice',
      'sort',
      'reverse'
    ].forEach(function (method) {
      const original = arrayProto[method]//缓存元素数组原型
      //这里重写了数组的几个原型方法
      def(arrayMethods, method, function mutator () {
        //这里备份一份参数应该是从性能方面的考虑
        let i = arguments.length
        const args = new Array(i)
        while (i--) {
          args[i] = arguments[i]
        }
        const result = original.apply(this, args)//原始方法求值
        const ob = this.__ob__//这里this.__ob__指向的是数据的Observer
        let inserted
        switch (method) {
          case 'push':
            inserted = args
            break
          case 'unshift':
            inserted = args
            break
          case 'splice':
            inserted = args.slice(2)
            break
        }
        if (inserted) ob.observeArray(inserted)
        // notify change
        ob.dep.notify()
        return result
      })
    })
    
    //定义属性
    function def (obj, key, val, enumerable) {
      Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
      });
    }
    

    上面的代码主要是继承了Array本身的原型方法,然后又做了劫持修改,可以发出通知。
      Vue在observer数据阶段会判断如果是数组的话,则修改数组的原型,这样的话,后面对数组的任何操作都可以在劫持的过程中控制。

    // 以上代码 相当于
    var bar = [1,2];
    bar.__proto__ = arrayMethod;
    // 执行
    bar.push(3); 就会触发arrayMethods中的代码:ob.dep.notify()就会被触发,就会通知watcher触发template的更新。
    

    相关文章

      网友评论

          本文标题:vue2.0的数组劫持

          本文链接:https://www.haomeiwen.com/subject/pntfgctx.html