Vue3设计与实现共读-响应系统(四)

113 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

分支切换与cleanup(一)

首先,我们需要明确分支切换的定义,如下面代码所示:

const data = {ok:true,text:'hello world'}
const obj = new Proxy(data,{/* ... */})

effect(function effectFn(){
	document.body.innerText = obj.ok ? obj.text : 'not'
})

在effectFn 函数内部存在一个三元表达式,根据字段obj.ok值的不同会执行不同的代码分支。当字段obj.ok的值发生变化时,代码执行的分支会跟着变化,这就是所谓的分支切换。

分支切换可能会产生遗留的副作用函数。就拿obj.ok的初始值为true,这时会读取字段obj.text的值,当effectFn函数执行时会触发字段obj.ok和字段obj.text这两个属性的读取操作,此时副作用函数effectFn与响应式数据之间建立的联系:

  • data

    • ok

      • effectFn
    • text

      • effectFn

图片.png

可以看到,副作用函数effectFn分别被字段data.ok和字段data.text所对应的依赖集合收集。当字段obj.ok的值修改为false,并触发副作用函数重新执行后,此时obj.text不会被读取,只会触发obj.ok 的读取操作,所以理想情况下副作用函数effectFn不应该被字段obj.text所对应的依赖集合收集。

但是按照上面的实现方式,我们还无法做到这一点,当我们修改字段obj.ok时,触发副作用函数执行,依旧还是会产生遗留的副作用函数。

遗留的副作用函数会产生不必要的更新。

const data = {ok:true, text:'hello world'}
const obj = new Proxy(data,{/* ... */})

effect(function effectFn(){
	document.body.innerText = obj.ok ? obj.text : 'not'
})

obj.ok的初始值为true,当将其修改为obj.ok = false后:

会触发更新,副作用函数会执行。此时obj.ok为false。不会读取obj.text的值。也就是说obj.text如何改变,innerText始终为not。这是我们想要的结果,但是实时并非如此,如果我们修改的obj.text,依旧会导致副作用函数的执行,即使不需要发生变化。

所以下一步我们就要通过重新设计副作用函数来实现副作用函数可以明确知道有哪些依赖集合包含自己。这个问题,我们下一篇文章中继续探讨。