【vue设计与实现】非原始值的响应式方案 9-隐式修改数组长度的原型方法

这次主要了解那些会隐式修改数组长度的方法,主要指的是数组的栈方法,如push/pop/shift/unshift以及splice
首先来看push方法
通过阅读规范得知当调用数组的push方法向数组中添加元素时,既会读取数组的length属性值,也会设置length的值,这就导致两个独立的副作用函数互相影响。这样会导致栈溢出的错误
所以通过“屏蔽”对length属性的读取,就能避免其与副作用函数建立响应联系,问题就解决了,毕竟push方法主要是修改操作而不是读取操作,这样不通过读取建立响应联系不会产生其他问题。所以我们要重写数组的push方法,如下面代码所示:

// 设置一个标记变量代表是否进行追踪,默认为true表示允许追踪
let shouldTrack = true
// 重写数组的push方法
;['push'].forEach(method => {
	// 取得原始push方法
	const originMethod = Array.prototype[method]
	// 重写
	arrayInstrumentations[method] = function(...args){
		// 在调用原始方法之前,禁止追踪
		shouldTrack = false
		// push方法的默认行为
		let res = originMethod.apply(this,args)
		// 在调用原始方法后,恢复允许追踪
		shouldTrack = true
		return res
	}
})

这里对push方法的重写保留了push的默认行为,只不过添加了shouldTrack,在执行默认行为之前,先将shouldTrack的值设置为false,默认行为执行完毕之后,再讲标记变量shouldTrack的值还原为true
最后还需要修改track函数,如下面代码所示:

function track(target, key){
	// 当禁止追踪时,直接返回
	if(!activeEffect || !shouldTrack) return
}

这样当push方法间接读取length时,由于此时时禁止追踪的状态,所以length属性不会和副作用函数建立响应联系。这样就不会出现调用栈溢出的问题。

除了push方法外,pop,shift,unshift以及splice方法都要做类似的处理,完整代码如下:

let shouldTrack = true
;['push','pop','shift','unshift','splice'].forEach(method => {
	const originMethod = Array.prototype[method]
	// 重写
	arrayInstrumentations[method] = function(...args){
		shouldTrack = false
		let res = originMethod.apply(this,args)
		shouldTrack = true
		return res
	}
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值