我有一个看起来像mobx的商店
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input type="hidden" class="check_sales_pack" name="check_sales_pack">
<input type="number" class="qty_pack" name="qty_pack" value="0" min="0" max="3">
<input type="number" class="qty_pack" name="qty_pack" value="0" min="0" max="3">
</div>
这是一个昂贵的计算值,带有子计算值,会在class EntityStore {
rootStore
@observable entityIndex = {}
constructor(rootStore){
this.rootStore = rootStore;
}
@action addEntities(entityArray){
entityArray.forEach((entity) => this.addEntity(entity));
}
@action addEntity(entityProps){
if(entityProps.id && this.entityIndex[entityProps.id]){
throw new Error(`Failed to add ${entityProps.id} an entity with that id already exists`);
}
const entity = new Entity({
...entityProps,
assetStore: this.rootStore.assetStore,
regl,
});
this.entityIndex[entity.id] = entity;
}
@computed get entityAssetIds(){
return Object.values(this.entityIndex).map(e => e.assetId);
}
@computed get renderPayload(){
const payloadArray = [];
for(let entityId in this.entityIndex){
payloadArray.push(this.entityIndex[entityId].renderPayload)
}
return payloadArray;
}
}
循环中以60fps的速度调用requestAnimationFrame
进行调用。我需要将其缓存。
使用entityStore.renderPayload()
,我得到了输出
trace
这让我感到惊讶,因为我的期望是Mobx仅在对计算值的依赖观测值发生更改时才会重新计算。
有什么办法强迫这种不可重新计算的行为吗?
更新我不使用反应。这是普通的mobx对象
答案 0 :(得分:1)
通常是您尝试使用不使用observer
(或reaction
或autorun
)的值时看到的行为。您不会提及您使用的是React还是其他库,也不会说明您如何访问该值。可能值得在CodeSandbox上建立一个最小的示例来重现您遇到的问题。
如果我不得不推测,我想说的是,您正在将计算值消耗在没有用observer
包装的组件中的某个位置(对于React)。 Here's一个示例(删除了未使用的方法)无需其他框架即可重现该问题:
import { autorun, computed, configure, observable } from "mobx";
class EntityStore {
@observable entityIndex = {};
@computed get renderPayload() {
const payloadArray = [];
for (let entityId in this.entityIndex) {
payloadArray.push(this.entityIndex[entityId].renderPayload);
}
return payloadArray;
}
}
configure({ computedRequiresReaction: true });
const store = new EntityStore();
// console.log('THIS WILL TRIGGER A WARNING:', store.renderPayload)
autorun(() => console.log('THIS WILL NOT TRIGGER A WARNING:', store.renderPayload))
如果取消注释日志,则应该看到控制台警告。可能是,您在observer
内或类似地方之外使用了计算值。如果您确定不是这种情况,则可以在问题中添加更多细节。
答案 1 :(得分:1)
Mobx不错,就像您在示例中的回购中将其命名一样,它真棒,它不会重新计算任何代码都未观察到的值。
要修正您的示例,只需在setInterval
前面加上这一行
observe(M, 'output', () => {})
现在MobX知道可以观察到输出,并且您的昂贵计算将只运行一次。直到一些相关的变量更改。
只需在开始动画循环之前观察使用的计算域,并在结束后进行处理,就可以像魔术一样工作。