vue3.2.26源码调试之数组方法

原以为proxy支持数组,不需要改写数组方法,但get与set都会触发两次

let arr = [1, 2];
let proxyArr = new Proxy(arr, {
  get(target, key, receiver) {
    console.log(`get`, key);
    const res = Reflect.get(target, key, receiver);
    return res;
  },
  set(target, key, value, receiver) {
    console.log(`set`, key, value);
    const res = Reflect.set(target, key, value, receiver);
    return res;
  },
});
proxyArr.push(3);

// get push
// get length
// set 2 3
// set length 3

vue3数组方法总结
1、get时,要重写数组方法

for (let i = 0, l = this.length; i < l; i++) {
        track(arr, TrackOpTypes.GET, i + '')
}

重写includes, indexOf, lastIndexOf三个方法,并且track每个元素作为依赖

;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      pauseTracking()
      const res = (toRaw(this) as any)[key].apply(this, args)
      resetTracking()
      return res
    }
})

重写push, pop, shift, unshift, splice四个方法,暂停track
2、set时,不需要重写数组方法

if (target === toRaw(receiver)) {
      if (!hadKey) {
        trigger(target, TriggerOpTypes.ADD, key, value)
      } else if (hasChanged(value, oldValue)) {
        trigger(target, TriggerOpTypes.SET, key, value, oldValue)
      }
}

数组新增元素时trigger更新,
修改元素时length相同,不走trigger

deps.push(depsMap.get('length'))

触发时有用到length更新

posted @ 2021-12-20 17:35  jerry-mengjie  阅读(253)  评论(0)    收藏  举报