MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程使得状态管理变得简单和可扩展。
React 和 MobX 是一对强力组合。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。
一、搭建环境依赖
安装mobx
npm install mobx mobx-react --save
或在浏览器上使用cdn
https://unpkg.com/mobx/lib/mobx.umd.js
https://cdnjs.com/libraries/mobx
二、启用装饰器语法:
大多数人使用mobx都会选择使用装饰器语法(你也可以选择不使用装饰器,则无需启用装饰器)。
使用装饰器语法的优势:
- 样板文件最小化,声明式代码。
- 易于使用和阅读。大多数 MobX 用户都在使用。
装饰器语法需要在es7或者在typescript中使用,如果你的环境不支持装饰器,需要手动开启开启装饰器语法。
1、安装装饰器所需依赖
npm install @babel/plugin-proposal-decorators --save-dev // 安装在本地即可
2、释放配置文件
npm run eject
如果出错,执行以下命令,再次执行释放配置文件:
git add .
git commit -am "msg"
3、修改package.json中的babel配置
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
]
]
}
到此已经配置完成。
三、基本使用
1、定义状态
使用装饰器:
import {action, observable, computed} from 'mobx';
class AppState {
@observable count = 0;
@computed get countText(){ // 计算值,当运算值中的其中一个值发生变化时都会重新计算
return '数值:' + this.count
}
@action.bound addCount(){ // 定义一个action,该action每次为count+1。 添加bound修饰绑定对象,可保证this指向永远正确的
this.count++
}
}
export default new AppState(); // 实例化当前类并导出
不使用装饰器:
import {action, observable, computed, decorate} from 'mobx'; // 注意导入decorate
class AppState {
count = 0;
get countText(){
return '数值:' + this.count
}
addCount(){ // 定义一个action,该action每次为count+1
this.count++
}
}
decorate(SppState,{
count: observable,
countText: computed,
addCount: action.bound // 添加bound修饰绑定对象,可保证this指向永远正确的
})
export default new AppState(); // 实例化当前类并导出
需要使用 decorate
工具,decorate
接受两个参数,第一个是目标对象,第二个参数为装饰器属性参数
2、创建视图
使用装饰器
import {observer} from 'mobx-react'
@observer
class Page extends React.Component {
render() {
return (
<div>
<button onClick={this.props.appState.addCount}>添加</button> // 如果定义action时没有使用bound修饰绑定对象,则需要使用匿名函数执行调用
当前数量:{this.props.appState.count}
</div>
)
}
}
export default Page;
不使用装饰器
import {observer} from 'mobx-react'
function Page(props) {
return (
<div>
<button onClick={this.props.appState.addCount}>添加</button> // 如果定义action时没有使用bound修饰绑定对象,则需要使用匿名函数执行调用
当前数量:{props.appState.count}
</div>
)
}
export default observer(Page); // 使其可观察并导出
3、绑定appState到视图组件上
import appState from './store/index' // 路径根据实际情况而定
import Timer from './pages/Timer' // 导入视图组件
function App() {
return (
<div>
<Timer appState={appState}></Timer> // 通过props传递
</div>
);
}
到此一个简单的示例已经完成了!
三、使用 Provider、inject 工具
接着上面示例,我们给视图组件传递store时,需在组件上传递props,目前看似无所谓,但是,如果组件多了,我们需要给给个组件都写上同样的props,比较麻烦,不易维护,不美观。我们可以通过引入Provider、inject解决此类问题。
1、Provider:
Provider是一个组件,一般包裹在左右视图组件的最外层,以实现所有组件的全局context,在所需组件里可以通过inject获取store。
import {Provider} from 'mobx-react';
import appState from 'store/index'; // 引入store
function App() {
return (
<Provider store={appState}> // 挂载全局store
<Timer></Timer>
</Provider>
);
}
mobx是可以拆分为多个store的,那么多个store如何挂载全局呢?
import {Provider} from 'mobx-react';
import {appState,appState2,appState3} as stores from 'store/index'; // 引入多个store
function App() {
return (
<Provider {...stores}> // 挂载全局store
<Timer></Timer>
</Provider>
);
}
2、inject
inject用于注入store, 在Provider包裹下的视图组件可以通过@inject('store')的方式注入。
@inject('store') // 按照挂载时的名称进行注入
class Page extends React.Component {...}
还可以注入多个store
@inject('store','store2','store3') // 注入多个store
class Page extends React.Component {...}
注入后,组件内可以通过 this.props.store的方式获得状态。
MobX中文文档:https://cn.mobx.js.org/
注:个人笔记,不作标准答案,仅供参考。