上一节遗留问题:
如果写两个effect,一个里面获取age,一个里面获取name,我们希望初始化时执行两个effect,渲染age和name,过一秒改变age,执行获取age的effect,而事实一秒后两个effect都执行了
代码:
effect(() => {
console.log('更新名字')
document.body.innerText = state.name
})
effect(() => {
console.log('更新年龄')
document.body.innerText = state.age
})
setTimeout(() => {
state.name = 'name更新'
}, 1000)
执行结果:
分别执行了两次,查看关联关系是这样的:
name关联了两个函数,当name更新,就把两个函数都取出来执行了。而我们希望name只关联取name值的,age只关联取age值的,为什么name会关联上两个呢。
我们只有一个activeEffect用来存放当前执行的函数,在函数执行完成后没有重置activeEffect,就会造成name更新去执行document.body.innerText = state.name这个语句时,对name取值,而此时activeEffect是保存state.age这个函数,就又会关联在name上
这里用栈来存放effect函数,当函数执行时入栈,activeEffect指向effect,执行完成后出栈,重置activeEffect为栈里最后一个,这样在age关联好后,栈里就没有函数了,name更新时执行document.body.innerText = state.name就不会再给name关联上,修改代码
export let effectStack = [] // 新增栈
export const effect = (fn: Function) => {
const effectFn = () => {
activeEffect = fn
effectStack.push(fn) // 将副作用函数压入栈
fn()
effectStack.pop() // 副作用函数执行完成后出栈
activeEffect = effectStack[effectStack.length - 1] // 将激活的函数指向最后一个
}
effectFn()
}