简介
mobx是一个简单、可扩展的状态管理库。
MobX 浏览器支持
- MobX5 任何支持ES6 proxy的浏览器 不支持IE11 node6
- MobX4 任何支持ES5的浏览器
- MobX4 和 MobX5的API是相同的
开发前准备
启用装饰器语法支持(方式一)
- npm run eject 暴露配置
- 下载装饰器语法babel插件 npm i @babel/plugin-proposal-decorators
- 在package.json文件中加入配置
启用装饰器语法支持(方式二)
- npm install react-app-rewired customize-cra @babel/plugin-proposal-decorators
- 在项目根目录下创建config-overrides.js并加入如下配置。
const { override, addDecoratorsLegacy } = require('customiza-cra')
module.exports = override(addDecoratorsLegacy())
- 更改package.json文件中的项目启动配置
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
VScode编辑器关于装饰器语法的警告
修改配置:“javascript.implicitProjectConfig.experimentalDecorators”: true
MobX的基本使用
安装
npm i mobx mobx-react
工作流程
计数器案例
// 1. 创建store对象 存储默认状态0
// 2. 将store对象放在一个全局的 组件可以够的到的地方
// 3. 让组件获取store对象中的状态 并将状态显示在组件中
import { observable, action, autorun } from 'mobx';
class CounterStore {
@action increment = () => {
this.count = this.count + 1;
}
@action decrement = () => {
this.count = this.count - 1;
}
}
const counter = new CounterStore();
export default counter;
index.js中使用 Provider、counter
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react';
import App from './App';
import counter from './stores/counterStore';
ReactDOM.render(
<Provider counter={counter}><App /></Provider>,
document.getElementById('root')
);
App.js中使用定义的counter //通过inject
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
@inject("counter")
@observer
class App extends Component {
render() {
const { counter } = this.props;
return (
<div>
<button onClick={counter.increment}>+</button>
<span>{counter.count}</span>
<button onClick={counter.decrement}>-</button>
</div>
);
}
}
export default App;
更正类中普通函数指向(bound)
// @action increment = () => {
// this.count = this.count + 1;
// }
// @action decrement = () => {
// this.count = this.count - 1;
// }
@action.bound increment () {
this.count = this.count + 1;
}
@action.bound decrement () {
this.count = this.count - 1;
}
异步更新状态
runInAction(异步操作更新状态)、bound(this问题)
在 action 函数中如果存在异步代码,更新状态的代码就需要包裹在runInAction方法中
@action.bound async getData () {
let { data } = await axios.get('https://api.github.com/users');
runInAction(() => this.users = data);
}
或者使用 flow(需要是generator函数)\bind
flow方法中可以执行异步操作,可以直接进行状态的更改
getData = flow(function* () {
let { data } = yield axios.get('https://api.github.com/users');
this.users = data
}).bind(this)
数据监测 computed
计算值(computed)是可以根据现有的状态或其它计算值衍生出的值。
什么时候使用计算值?将复杂的业务逻辑从模板中进行抽离。
@observable count = 0;
@computed get getResult () {
return this.count * 10
}
禁止普通函数修改状态【必须通过action函数】
// 通过配置强制程序使用action函数更改应用程序中的状态
configure({enforceActions: 'observed'});
通过action装饰器 装饰普通函数
@action increment = () => {
this.count = this.count + 1;
}
数据监测 autorun
当监测的状态发生变化时,你想根据状态产生 “效果”[去干一件事,而不是求值],请使用 autorun。
autorun 会在初始化的时候执行一次,会在每次状态发生变化时执行
import { observable, configure, action, runInAction, flow, computed, autorun } from 'mobx';
class CounterStore {
constructor () {
autorun (() => {
try {
uniqueUsername(this.username)
console.log('用户名可用')
}catch (e) {
console.log(e.message)
}
}, {
delay: 2000
})
}
@observable username = '';
@action.bound changeUsername (username) {
this.username = username;
}
}
const counter = new CounterStore();
function uniqueUsername (username) {
return new Promise((resolve, reject) => {
if (username === 'admin') {
reject('用户名已经存在')
}else {
resolve()
}
})
}
export default counter;