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 = 0
amount = 1
constructor(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: 0
console.log(order.total)
// (No recomputing!)
// 0
order.amount = 5
// Computing...
// (No autorun)
order.price = 2
// Computing...
// Total: 10
stop()
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 effects
return 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 value
return 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 value
return this.value * 2;
// Bad: This computed value depends on a non-observable value
// return this.nonObservableValue * 2;
}
}