构建一个动态的可监听树

迄今为止,我们的模型在单层数据结构运行得很好,但是要求我们手工把每个新对象-值属性封装为可监听。例如,如下代码将不能按预期运行。

  1. const person = observable({data: {name: 'John'}})
  2. function print () {
  3. console.log(person.data.name)
  4. }
  5. // outputs 'John' to the console
  6. observe(print)
  7. // does nothing
  8. setTimeout(() => person.data.name = 'Dave', 100)

为了让代码运行,我们不得不把 observable({data: {name: 'John'}}) 替换为 observable({data: observable({name: 'John'})})。幸运的是,我们可以通过稍微修改 get 陷阱函数来去除这种不便。

  1. function get (target, key, receiver) {
  2. const result = Reflect.get(target, key, receiver)
  3. if (currentObserver) {
  4. registerObserver(target, key, currentObserver)
  5. if (typeof result === 'object') {
  6. const observableResult = observable(result)
  7. Reflect.set(target, key, observableResult, receiver)
  8. return observableResult
  9. }
  10. }
  11. return result
  12. }

如果返回值是一个对象的时候,上面的 get 陷阱函数会在返回之前把返回值设置为一个可监听的代理对象。从性能的角度来看,这也是相当完美的方案,因为可监听对象仅当监听函数需要的时候才创建。