我怎样才能观察到任何改变(属性添加,删除或改变)在mobx观察到的地图吗?

问题描述 投票:1回答:1
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' },但似乎反应不运行。

我怀疑,我成立了以错误的方式反应。我想,每当一个新的关键是增加,现有的密钥被删除或键值改为反应。我不知道在编译时的键或值。

我应该怎么做呢?

UPDATE

我改变了我的代码

class FilterCriteria {
    @observable filter = new Map();
    @computed get json(){ return this.filter.toJSON(); }
}
...
reaction(()=>criteria.json, data => console.log(data));

现在看来正常工作。将反应sideffect执行每当添加,删除或更改在映射中的值。

所以,问题是为什么反应并在第二,但不是在第一个例子中执行呢?

更新2

我再一次改变了我的代码的第二次。我回复到几乎与第一版本,但此时代替上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东西被改变重新评估?

UPDATE 4(希望最后一个)解决方案

据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 mobx-react
1个回答
1
投票

在mobx你有两个选择,当你想观察变化的东西,是可观察的。 reactionobserveReaction允许您指定当你想调用一些功能的可观察到的变化的具体方面时。这可能是改变数组的长度,密钥,性质,真的什么。 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"}

显然,该值比{}不同,所以东西已经改变,并且该反应的第二函数被调用。

© www.soinside.com 2019 - 2024. All rights reserved.