mobx是一个简单、可扩展状态工具,相比redux,具有以下特点
注:mobx6默认不开启修饰器语法
新建一个ts的react项目
npx create-react-app my-app --template typescript
安装mobx库
yarn add mobx mobx-react --save
注:轻量级的mobx-react-lite只支持函数组件
以一个计数器为例,创建文件store/Counter.ts,新建一个Counter类,使用makeObservable方法将类的属性和方法变成响应式,并导出实例
注:mobx中的每一个store都应该只初始化一次
// store/Counter.ts
import {action, makeObservable, observable} from 'mobx'
class Counter {
constructor(){
// 参数1:target,把谁变成响应式(可观察)
// 参数2:指定哪些属性或者方法变成可观察
makeObservable(this, {
count: observable,
increment: action,
decrement: action,
reset: action,
})
}
count = 0
increment(){
this.count++
}
decrement(){
this.count--
}
reset(){
this.count = 0
}
}
const counter = new Counter()
export default counter
在组件中使用,需要在App.tsx文件中引入store,即可使用其属性方法
// App.tsx
import counter from './store/Counter';
// observer是一个高阶组件函数,需要包裹一个组件,这样组件才会更新
import { observer } from 'mobx-react'
function App() {
const {cart, counter} = useStore()
return (
<div className="App">
<h3>计数器案例</h3>
<div>点击次数:{counter.count}</div>
<button onClick={()c=> ounter.increment()}>加1</button>
<button onClick={()c=> ounter.decrement()}>减1</button>
<button onClick={() => counter.reset()}>重置</button>
</div>
);
}
export default observer(App);
默认class中的方法不会绑定this,this指向取决于如何调用。Counter里面的方法的this没有绑定,因此需要通过箭头函数的形式使用
<button onClick={()c=> ounter.increment()}>加1</button>
要想直接使用,需要在Counter里面的makeObservable的使用通过action.bound绑定this的指向
makeObservable(this, {
count: observable,
increment: action.bound,
reset: action.bound,
})
此时组件中即可直接使用store的方法
<button onClick={counter.increment}>加1</button>
mobx的computed可以用来从其他可观察对象中派生信息,具有以下特点:
...
makeObservable(this, {
count: observable,
increment: action.bound,
reset: action.bound,
double: computed,
})
...
get double(){
return this.count * 2
}
makeAutoObservable是加强版的makeObservable,在默认情况下它将推断所有属性。推断规格如下:
// 参数1:target,把谁变成响应式(可观察)
// 参数2:排除属性和方法
// 参数3:指定自动绑定this
makeAutoObservable(this, {}, {autoBind: true})
mobx中有两个监听方法autorun和reaction,其中:
autorun(() => {
console.log('counter', counter.count);
})
reaction(
() => counter.count,
(newValue, oldValue) => {
console.log('counter.count变化了');
}
)
异步进程在mobx中不需要任何特殊处理,因为不论是何时引发的所有reaction都将会自动更新,这是因为可观察对象是可变的,在action执行过程中保持对它们的引用一般是安全的。
如果可观察对象的修改不是在action函数中,控制台会报警告,这是可以通过runInAction保证所有异步更新可观察对象步骤都标识为action
incrementAsync(){
setTimeout(() => {
runInAction(() => {
this.count++
})
}, 2000)
}
mobx模块化管理即通过一个根store统一管理所有store
新建store/index.ts文件,导入所有store,使用useContext机制,自定义useStore hook,统一导出store
import { useContext, createContext } from 'react'
import cart from './Cart'
import counter from './Counter'
class RootStore {
cart = cart
counter = counter
}
const store = new RootStore()
const Context = createContext(store)
export const useStore = () => {
return useContext(Context)
}
在App.tsx中统一导入,解构得到相应store
import {useStore} from './store'
...
const {cart, counter} = useStore()
...
文章完整代码地址:https://github.com/Stars-Chan/mobx-induction
Refs: 【前端】三小时带你玩转mobx