文件目录
packages/reactivity/src/effect.ts
作用
依赖收集/更新
源码解读
function effect(fn, options) {
if (fn.effect instanceof ReactiveEffect) {
fn = fn.effect.fn
}
const e = new ReactEffect(fn)
if(options) {
extend(e, fn)
}
try{
e.run()
} catch(err) {
e.stop()
throw err
}
}
class ReactiveEffect {
deps? = undefined
depsTail? = undefined
flags = EffectFlags.ACTIVE | EffectFlags.TRACKING
nextEffect? = undefined
cleanup?() => void = undefined
scheduler? = undefined
onStop?: () => void
onTrack?: () => void
onTrigger?: () => void
constructor(fn) {
if (activeEffectScope && activeEffectScope.active) {
activeEffectScope.effects.push(this)
}
}
pause() {}
resume() {}
run() {
if (!(this.flags & EffectFlags.ACTIVE)) {
return this.fn()
}
this.flags |= EffectFlags.RUNNING
cleanupEffect(this)
prepareDeps(this)
const prevEffect = activeSub
const prevShouldTrack = shouldTrack
activeSub = this
shouldTrack = true
try {
return this.fn()
} finally {
cleanupDeps(this)
activeSub = prevEffect
shouldTrack = prevShouldTrack
this.flag &= ~EffectFlags.RUNNING
}
}
strop() {}
trigger() {}
}
cleanupEffect
- 把当前激活 effect 赋值给 前一个
- 清理当前激活 effect
function cleanupEffect(e) {
const { cleanup } = e
e.cleanup = undefined
if (cleanup) {
const prevSub = activeSub
activeSub = undefined
try {
cleanup()
} finally {
activeSub = prevSub
}
}
}
prepareDeps
function prepareDeps(sub) {
for( let link = sub.deps; link; link = link.nextDep) {
link.version = -1
link.preActiveLink = link.dep.activeLink
link.dep.activeLink = link
}
}
cleanupDeps
function cleanupDeps(sub) {
let head
let tail = sub.depsTail
for(let link = tail; link; link = link.prevDep) {
if (link.version === -1) {
if (link === tail) tail = link.prevDep
removeSub(link)
removeDep(link)
} else {
head = link
}
link.dep.activeLink = link.prevActiveLink
link.prevActiveLink = undefined
}
sub.deps = head
sub.depsTail = tail
}