仿写Vue八、添加数组的方法

762 阅读2分钟

八、添加数组的方法

 自己动手实践,就会更加深刻的理解**”**

这次处理数组的七个方法,使其成为响应式。

01、获取数组原型对象


重写每一个函数不现实,所以打算先获取数组的原型对象,然后生成一个新的对象来继承此原型对象,这个新的对象就拥有数组的一切属性方法,且不会对原生的数组产生任何影响。

/** 
* 对与响应式数组,我们需要重写其一些方法,例如 push、pop 
* 保证响应式数组使用这些方法之后依然是响应式的。 
*/
const arrProto = Array.prototype;
const arrMethods = Object.create(arrProto);

02、重写方法


我们需要覆盖七个方法:

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

对于 push, pop, splice,响应式数组唯一不同的地方在于,对于往数组新加的数据项,需要保证其仍然是响应式的。其他的方法,要么是更改数据的位置,要么是删除某些数据,都不需要额外的处理,只需调用原来的方法即可。

function def(obj, key, val, enumerable) {
  Object.defineProperty(obj, key, {
    value: val,
    enumerable: !!enumerable,
    configurable: true,
    writable: true,
  })
}

methodsToPatch.forEach(method => {
  const original = arrMethods[method];
  def(arrMethods, method, function mutate() {
    console.log('调用的方法是:', method);
    
    let args = [], len = arguments.length;
    while (len--) args[len] = arguments[len];
    const result = original.apply(this, args);
    let inserted;
    const ob = this.__ob__;
    switch(method) {
      case 'push':
      case 'unshift':
        inserted = args; break;
      case 'splice':
        inserted = args.slice(2); break;
    }
    // 如果有新增的数据,则每个数据都将其响应式化
    if (inserted) {
      ob.observeArray(inserted);
    }
    return result;
  })
})

03、效果图


数据初始化:

    const data = {
      name: 'romeo',
      message: 'wants to be rich',
      deep: {
        firstLevel: {
          secondLevel: 'here!'
        }
      },
      arr: [
        { name: 'jack1' },
        { name: 'jack2' },
        { name: 'jack3' },
      ]
    }


可以看到 arr 中确实拥有了第四项,且同样是响应式的。

源代码在github上,请点击阅读原文查看~
公众号二维码.png