The above example nicely demonstrates the benefits of a
computed
value, it acts as a caching point. Even though we change theamount
, and this will trigger thetotal
to recompute, it won’t trigger theautorun
, astotal
will detect its output hasn’t been affected, so there is no need to update theautorun
上述描述了,computed 复合属性total的计算过程,复合属性total包含price和amount两个子属性,total = price * amount。当computed返回值price * amount不变,则不会触发autorun中total changed的回调函数。
示例
import { makeObservable, observable, computed, autorun } from "mobx"class OrderLine {price = 0amount = 1constructor(price) {makeObservable(this, {price: observable,amount: observable,total: computed})this.price = price}get total() {console.log("Computing...")return this.price * this.amount}
}const order = new OrderLine(0)const stop = autorun(() => {console.log("Total: " + order.total)
})
// Computing...
// Total: 0console.log(order.total)
// (No recomputing!)
// 0order.amount = 5
// Computing...
// (No autorun)order.price = 2
// Computing...
// Total: 10stop()order.price = 3
// Neither the computation nor autorun will be recomputed.
3个computed使用规则
Rules When using computed values there are a couple of best practices to follow:
They should not have side effects or update other observables. Avoid creating and returning new observables. They should not depend on non-observable values.
它们不应该有副作用或更新其他可观察对象。
computed
值应该是纯粹的,这意味着它们不应该改变任何状态,也不应该有任何副作用。它们只应该根据它们的依赖项计算新的值。
class Store {@observable value = 0;@observable otherValue = 0;@computed get double() {// Good: This computed value doesn't have any side effectsreturn this.value * 2;// Bad: This computed value has a side effect// this.otherValue = this.value * 2;// return this.otherValue;}
}
避免创建和返回新的可观察对象。
computed
值应该返回一个简单的值,而不是一个新的可观察对象。如果你的computed
值返回一个新的可观察对象,那么每次这个computed
值被重新计算时,都会创建一个新的可观察对象。
class Store {@observable value = 0;@computed get double() {// Good: This computed value returns a simple valuereturn this.value * 2;// Bad: This computed value returns a new observable// return observable({ double: this.value * 2 });}
}
它们不应该依赖非可观察值。
computed
值应该只依赖可观察对象的状态。如果你的computed
值依赖非可观察值,那么当这个值改变时,MobX无法知道需要重新计算computed
值。
class Store {@observable value = 0;nonObservableValue = 0;@computed get double() {// Good: This computed value depends on an observable valuereturn this.value * 2;// Bad: This computed value depends on a non-observable value// return this.nonObservableValue * 2;}
}