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更新