如何在MobX中处理循环引用?

时间:2017-02-21 09:48:22

标签: javascript mobx

我有这段代码:

var root = {};
var left = {};
rootClass.left = left;
var right = {};
right.left = left;
left.right = right;
var o = observable(root);

right指针指向leftleft指针指向right。 当最后一行执行时,我收到此错误:

RangeError: Maximum call stack size exceeded
    at _tryDefineProperty (vendor.bundle.js:91185)
    at Function.Object.defineProperty (vendor.bundle.js:91141)
    at addHiddenFinalProp (vendor.bundle.js:14605)
    at asObservableObject (vendor.bundle.js:14122)
    at Function.IObservableFactories.object (vendor.bundle.js:12329)
    at deepEnhancer (vendor.bundle.js:13382)
    at new ObservableValue (vendor.bundle.js:14280)
    at defineObservableProperty (vendor.bundle.js:14163)
    at defineObservablePropertyFromDescriptor (vendor.bundle.js:14143)
    at extendObservableHelper (vendor.bundle.js:12207)
    at extendObservable (vendor.bundle.js:12178)
    at Function.IObservableFactories.object (vendor.bundle.js:12330)
    at deepEnhancer (vendor.bundle.js:13382)
    at new ObservableValue (vendor.bundle.js:14280)
    at defineObservableProperty (vendor.bundle.js:14163)

如何在MobX中处理循环引用?

1 个答案:

答案 0 :(得分:1)

MobX背后的理念是Excel电子表格。您需要考虑可以派生哪些数据以及哪些数据可以派生出来。

如果您的对象具有带键的圆形结构,则引用是派生数据的一个很好的示例。

您最终要做的只是将id键入的所有对象存储在对象(或MobX Map)中。

接下来,而不是创建左右属性,而不是创建计算的getter和setter。

左右对象id将存储在属性中(例如leftId和rightid)。

getter将通过查看根对象库中的leftId来简单地解析左侧或右侧。 setter将简单地提供一个逻辑来将id存储在leftId / rightId属性中,而不是存储整个对象。

observable({
    id: nextId(), // progressive id for sample
    name,
    leftId: null, // variables to store the id in {$ref: 1}
    rightId: null,
    get left(){ // getters and setters
      return allItems.has(this.leftId) ? 
        allItems.get(this.leftId) : 
        null
    },
    set left(item){
      this.leftId = item ? item.id : null
    },
    get right(){
      return allItems.has(this.rightId) ? 
        allItems.get(this.rightId) : 
        null
    },
    set right(item){
      this.rightId = item ? item.id : null
    },
  })

整个小提琴示例: https://jsfiddle.net/4ure5kak/2/