编程活动中,经常遇到这样的情况。b由a产生,当a变了的时候b也要自动变化。
一个简单的实现是这样的:
let subscribers = new Set()
// get a不像event listener那样,有传入callback function
// 所以这里维护一个activeJob,用于被加入队列
let activeJob = null
// 这里定义变量a
let a = 3
const state = {
get a () {
// 被赋值或用于计算时,添加观察者
// 使用Set避免重复添加
subscribers.add(activeJob)
return a
},
set a (newValue) {
// 被设值时通知所有观察者
a = newValue
subscribers.forEach(job => job())
}
}
// autorun接受更新函数作为参数
// 每次更新
const autorun = update => {
function job () {
activeJob = job
update()
activeJob = null
}
job()
}
// 最后调用autorun驱动
let view = null
const render = (state) => {
return JSON.stringify(state)
}
// 每次autorun会生成新的唯一的job
autorun(() => {
view = render(state)
})
// 尝试改变state.a,并观察view的改变
autorun执行时,会调用job,设置当前activeJob,随后由于 view = render(state) 中对state.a的引用, getter会被调用到。于是就添加上了观察者。
当state.a变化时,setter被调用,从而通知所有的观察者执行update。