mobx是和react搭配使用的状态管理库,没有redux那么多的概念和编码规范。
随着官方的升级,mobx6的用法和mobx5有了稍微不同的区别。
核心API的用法变动
observable state
把对象,数组,Maps 和 Sets 都可以被转化为可观察对象。
在mobx5中的用法
import { observable, computed } from "mobx";
class OrderLine {
@observable price = 0;
@observable amount = 1;
@computed get total() {
return this.price * this.amount;
}
}
在mobx6中, 不再需要装饰器这种写法了,搭配react17会报错。
mobx6,可以使用makeObservable在类的构造函数中使用。
import { makeObservable, observable, computed, action, flow } from "mobx"
class Doubler {
value
constructor(value) {
makeObservable(this, {
value: observable,
double: computed,
increment: action,
fetch: flow
})
this.value = value
}
get double() {
return this.value * 2
}
increment() {
this.value++
}
*fetch() {
const response = yield fetch("/api/value")
this.value = response.json()
}
}
action
在mobx5中 action的写法
class Ticker {
@observable tick = 0
@action.bound
increment() {
this.tick++ // 'this' 永远都是正确的
}
}
const ticker = new Ticker()
setInterval(ticker.increment, 1000)
在mobx6中,action 也可以放入构造函数constructor中
import { makeObservable, observable, action } from "mobx"
class Doubler {
value = 0
constructor(value) {
makeObservable(this, {
value: observable,
increment: action
})
}
increment() {
// 观察者不会看到中间状态.
this.value++
this.value++
}
}
computed计算值
在mobx5中 computed计算值,同样是加装饰器来处理。
在mobx6中,同样是写在构造函数中
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
}
}
makeAutoObservable
makeAutoObservable(target, overrides?, options?) makeAutoObservable与makeObservable类似。
自定义observable
在某些情况下,您可能希望有更多的数据结构或其他东西(如流),用于响应式计算。 通过使用原子的概念来实现这一点非常简单。 可以使用Atoms向MobX发出信号,表示某些可观察数据源已经被观察到或已经更改,而MobX将在atom被使用或不再使用时,向atom发出信号.
import { createAtom, autorun } from "mobx"
class Clock {
atom
intervalHandler = null
currentDateTime
constructor() {
// 创建一个atom来与MobX进行交互
this.atom = createAtom(
// 第一个参数是:
// - Atom的名称 用于在程序debug时便于观察.
"Clock",
// 第二个参数是(可选):
// - 在unobserved 变到 observed时的回调函数
() => this.startTicking(),
// 第三个参数是(可选):
// - 在observed 变到 unobserved时的回调函数
() => this.stopTicking()
// 同一个atom在多个状态之间来回变化
)
}
getTime() {
// 通知MobX这个observable 数据源已经被使用。
//
// 如果atom当前状态是 正在被观察(observed),reportObserved将返回true
// 通过 reaction.在需要时,它会被切换成“startTicking”(开始计时)
// onBecomeObserved处理函数.
if (this.atom.reportObserved()) {
return this.currentDateTime
} else {
// 调用了getTime函数,但此时没有任何reaction在运行,隐藏没有人依赖此值。所以并且不会触发startTicking和onBecomeObserved处理程序。
// 在这种情况下,根据atom的性质,其行为可能会有所不同,例如引发错误,返回默认值等。
return new Date()
}
}
tick() {
this.currentDateTime = new Date()
this.atom.reportChanged() // 通知MobX这个数据源已经更改。
}
startTicking() {
this.tick() // 初始化 tick
this.intervalHandler = setInterval(() => this.tick(), 1000)
}
stopTicking() {
clearInterval(this.intervalHandler)
this.intervalHandler = null
}
}
const clock = new Clock()
const disposer = autorun(() => console.log(clock.getTime()))
// 控制台打印输出运行中的“每一秒”
// 如果没有其他人使用同样的“clock”,它也会停止滴答作响。并且停止在控制的输出
disposer()
创建惰性 observables
onBecomeObserved(observable, property?, listener: () => void): (() => void)onBecomeUnobserved(observable, property?, listener: () => void): (() => void)
onBecomeObserved和onBecomeUnobserved方法可以给现有的可观察对象附加惰性行为或副作用。它们是MobX可观察系统的钩子并且 当可观察对象开始和停止被观察时,它们会得到通知。它们都返回一个用来取消listener的disposer函数。
export class City {
location
temperature
interval
constructor(location) {
makeAutoObservable(this, {
resume: false,
suspend: false
})
this.location = location
// 只有在实际使用温度时才开始获取数据!
onBecomeObserved(this, "temperature", this.resume)
onBecomeUnobserved(this, "temperature", this.suspend)
}
resume = () => {
log(`Resuming ${this.location}`)
this.interval = setInterval(() => this.fetchTemperature(), 5000)
}
suspend = () => {
log(`Suspending ${this.location}`)
this.temperature = undefined
clearInterval(this.interval)
}
fetchTemperature = flow(function* () {
// 获取数据的逻辑...
})
}
config 配置
mobx6支持你配置你的使用偏好。这包括:
-
useProxies是否MobX 只能运行在支持Proxy的环境中 -
enforceActionsenforceActions 配置的目的是让你不会忘记使用action包裹事件处理函数 -
computedRequiresReaction禁止在action或者reaction之外,直接获取未被观察的计算属性的值
import { configure } from "mobx"
configure({
enforceActions: "always",
computedRequiresReaction: true,
reactionRequiresObservable: true,
observableRequiresReaction: true,
disableErrorBoundaries: true
})
装饰器的未来
在版本6之前,Mobx鼓励使用ES.next中的decorators,将某个对象标记为observable, computed 和 action。然而,装饰器语法尚未定案以及未被纳入ES标准,标准化的过程还需要很长时间,且未来制定的标准可能与当前的装饰器实现方案有所不同。出于兼容性的考虑,我们在MobX 6中放弃了它们,并建议使用makeObservable / makeAutoObservable代替