class FilterCriteria {
@observable filter = new Map();
}
let criteria = new FilterCriteria ();
// setting up a reaction when something in the filter changes
// (property added, removed, or changed)
reaction(()=>criteria.filter, data => console.log(data.toJSON()));
criteria.filter.set('name', 'John'); // setting a new property.
我希望上面的代码打印出来{ 'name': 'John' }
,但似乎反应不运行。
我怀疑,我成立了以错误的方式反应。我想,每当一个新的关键是增加,现有的密钥被删除或键值改为反应。我不知道在编译时的键或值。
我应该怎么做呢?
我改变了我的代码
class FilterCriteria {
@observable filter = new Map();
@computed get json(){ return this.filter.toJSON(); }
}
...
reaction(()=>criteria.json, data => console.log(data));
现在看来正常工作。将反应sideffect执行每当添加,删除或更改在映射中的值。
所以,问题是为什么反应并在第二,但不是在第一个例子中执行呢?
我再一次改变了我的代码的第二次。我回复到几乎与第一版本,但此时代替上criteria.filter
和记录data.toJSON()
反应,我上criteria.filter.toJSON()
反应并我登录data
(的toJSON从sideffect到值移动正在观看)。这时将反应正常运行。
class FilterCriteria {
@observable filter = new Map();
}
reaction(()=>criteria.filter.toJSON(), data => console.log(data));
同样,我不明白为什么。如果criteria.filter
本身不是一个可观察的则是如何被监视的表达式是当内部criteria.filter东西被改变重新评估?
据MobX文档,mobx反应即是跟踪功能的执行过程中读取任何现有的可观测性能。
反应副作用执行观察的属性发生变化时。在我的例子,反应criteria.filter
时,也就是在这里读的观察特性是filter
,但过滤器本身永远不会改变。它始终是相同的地图。这是过滤器,改变了性质。所以反应从不为criteria.filter
运行。
但是,当我上criteria.filter.toJSON()
或mobx.toJS(criteria.filter)
反应,该反应是正确执行。
那么,为什么会这样? criteria.filter
不会改变,而toJSON
不是一个观察的属性。这是一个功能。同为mobx.toJS
。这似乎没有属性将在这里阅读。但是,这是不正确的。作为文档状态(但不那么强调),criteria.filter的属性时执行的toJSON或mobx.toJS确实读,因为这两个功能创建地图的深克隆(因此遍历每个属性)。
现在,在开始的时候,地图不包含任何属性。那么是什么让新加入的特性进行跟踪,因为它们不存在(被读取)在跟踪开始?这是一个地图的功能。地图尚未现有属性也提供可观性。
在MobX 5,你可以跟踪观察对象(不是类实例)的不存在性也提供了他们与观察到的或observable.object instatiated。类实例并不支持这一点。
在mobx你有两个选择,当你想观察变化的东西,是可观察的。 reaction
和observe
。 Reaction
允许您指定当你想调用一些功能的可观察到的变化的具体方面时。这可能是改变数组的长度,密钥,性质,真的什么。 observe
会引发一些功能,可观察到已经改变的任何时间。
我怀疑你的反应没有被触发的原因是因为第一个功能。 () => criteria.filter
。当一个键被添加/删除这不会被触发或值改变。相反,当实际filter
变化,它会被触发。而且,由于filter
是真的到了地图的参考,它永远不会改变,即使在地图本身的变化。
下面是一些例子来说明我的观点:
如果要触发一个反应,当一个密钥已经被添加或删除,您可能希望你的函数为:
() => criteria.filter.keys()
此函数的结果将是不同的,当一个键已被添加或移除。同样,如果您想要触发当值已被修改的反应,这样的事情应该工作:
() => criteria.filter.values()
因此,这两个的组合应该是你需要听更改键/值什么。另外,您也可以使用observe
,这将触发每一个变化,需要你检查发生了什么变化,以确保您的特定条件得到满足,以保证调用一个函数(即键/值变动)
更新:下面是说明该问题的示例
@observable map = new Map();
让说地图在内存中的值为5。所以,当你检查map === map
,它相当于5 === 5
并将评价为true。
现在,看着第一代码片段您发布的评论:
reaction(() => map, data => console.log(map.toJSON()));
每次添加/删除键或更改某个值,首先,函数就会运行。其结果将是5,因为这是我们说在内存中的值是这个例子。它会说:旧的值是5,而新值为5,所以没有变化。因此,反应将不运行的第二功能。
现在第二个片段:
reaction(() => map.toJSON(), data => console.log(data));
起初,函数的结果将是:{}
因为地图是空的。现在,让我们来添加一个关键:
map.set(1, 'some value');
现在,第一个函数的结果将是:
{"1": "some value"}
显然,该值比{}
不同,所以东西已经改变,并且该反应的第二函数被调用。