【vue设计与实现】非原始值的响应式方案 5-浅响应和深响应

这次来介绍reactiveshallowReactive的区别,也就是深响应和浅响应的区别
首先我们现在实现的reactive是浅响应的,就拿下面代码来说:

const obj = reactive{
	foo: {bar:1}
}
effect(()=>{
	console.log(obj.foo.bar)
})
//修改obj.foo.bar的值,并不能触发响应
obj.foo.bar = 2

为什么修改obj.foo.bar不能触发副作用函数重新执行。来看下现在的实现:

function reactive(obj){
	return new Proxy(obj, {
		get(target, key, receiver){
			if(key === 'raw'){
				return target
			}
			track(target, key)
			// 当读取属性值时,直接返回结果
			return Reflect.get(target, key, receiver)
		}
	})
}

看上面的代码,要读取obj.foo.bar,首先要读取obj.foo的值。由于通过Reflect.get得到obj.foo的结果是一个普通对象,并不是一个响应式对象,所以在副作用函数中访问时不能建立响应联系。要解决这个问题,就要对Reflect.get返回的结果做一层包装:

function reactive(obj){
	return new Proxy(obj, {
		get(target, key, receiver){
			if(key === 'raw'){
				return target
			}
			track(target, key)
			const res = Reflect.get(target, key, receiver)
			if(typeof res === 'object' && res !== null){
				// 调用reactive将结果包装成响应式数据并返回
				return reactive(res)
			}
			return res
		}
	})
}

当Reflect返回的值是对象,则递归地调用reactive函数并将其包装称响应式数据并返回。这样通过obj.foo.bar读取bar属性值时,自然就会建立响应联系,这样修改值时,就能够触发副作用函数重新执行。

但是不是所有情况下都要是深响应的,这就催生了shallowReactive,即浅响应,指的是只有对象的第一层属性是响应的。例如:

const obj = shallowReactive({foo:{bar:1}})
effect(()=>{
	console.log(obj.foo.bar)
})
// obj.foo是响应的,可以触发副作用函数重新执行
obj.foo = {bar:2}
// obj.foo.bar不是响应的,不能触发副作用函数重新执行
obj.foo.bar = 3

在这例子,我们使用shallowReactive函数创建一个浅响应的代理对象obj。要实现此功能,看下面代码:

// 封装createReactive函数,接收一个参数isShallow,代表是否为浅响应,默认为false
function createReactive(obj, isShallow = false){
	return new Proxy(obj, {
		get(target, key, receiver){
			if(key === 'raw'){
				return target
			}
			track(traget, key)
			const res = Reflect.get(target, key, receiver)
			//如果是浅响应,则直接返回原始值
			if(isShallow){
				return res
			}
			if(typeof res === 'object' && res !== null){
				return reactive(res)
			}
			return res
		}
	})
}

这样就实现了reactive以及shallowReactive函数

function reactive(obj){
	return createReactive(obj)
}
function shallowReactive(obj){
	return createReactive(obj, true)
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值