什么是Mobx
一个简单,可拓展的状态管理工具
安装
npm install mobx --save
核心概念
State(状态)
状态是驱动应用的数据,状态的改变会影响视图。
import {observable, autorun} from 'mobx';
var todoStore = observable({
/* 一些观察的状态 */
todos: []
});
Derivations(衍生)
任何源自状态并且不会再有任何进一步的相互作用的东西就是衍生。
import {observable, autorun} from 'mobx';
var todoStore = observable({
/* 一些观察的状态 */
todos: [],
/* 衍生值 */
get completedCount() {
return this.todos.filter(todo => todo.completed).length;
}
});
注意:衍生值必须是纯函数
Actions(动作)
动作是一段可以改变状态的代码。用户事件、后端数据推送、预定事件、等等。
使用原则
MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。
1、当状态改变时,所有衍生都会进行原子级的自动更新。
2、所有衍生默认都是同步更新。这意味着例如动作可以在改变状态之后直接可以安全地检查计算值。
3、计算值 是延迟更新的。任何不在使用状态的计算值将不会更新,直到需要它进行副作用(I / O)操作时。 如果视图不再使用,那么它会自动被垃圾回收。
4、所有的计算值都应该是纯净的。它们不应该用来改变状态。
举个例子:
import { observable,computed, action } from 'mobx';
class ObservableTodoStore {
//定义可响应状态
@observable todos = [];
@observable pendingRequests = 0;
//衍生值
@computed get completedTodosCount() {
return this.todos.filter(
todo => todo.completed === true
).length;
}
@computed get report() {
if (this.todos.length === 0)
return "";
return `Next todo: "${this.todos[0].task}". ` +
`Progress: ${this.completedTodosCount}/${this.todos.length}`;
}
//动作
@ction
addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: null
});
}
}
const observableTodoStore = new ObservableTodoStore();
使用装饰器@
装饰器会看起来更友好一些,使用babel-preset-mobx
npm install --save-dev babel-preset-mobx
安装后在package.json中配置
解决异步更新state
class Store {
//定义状态
@observable listData = []
@observable state = "pending";
//异步行为修改状态,比如向服务器请求数据
@action
async fetchProjects() {
this.state = "pending"
try {
const filteredProjects = await ajaxData();
// await 之后,再次修改状态需要动作:
runInAction(() => {
this.state = "done"
this.listData = filteredProjects
})
} catch (error) {
runInAction(() => {
this.state = "error"
})
}
}
}
runInAction是一个工具函数。只在动作中运行回调函数中状态修改的部分,而不是为整个回调创建一个动作。 这种模式的优势是它鼓励你不要到处写 action,而是在整个过程结束时尽可能多地对所有状态进行修改。
一个完整的例子:
整个应用状态管理入口:
import React from 'react';
import ReactDOM from 'react-dom';
import { ConfigProvider } from 'antd';
import App from './App';
import zhCN from 'antd/es/locale/zh_CN';
import { Provider } from 'mobx-react';
import stores from '@/stores'
ReactDOM.render(
, document.getElementById('root'));
store统一管理:
import permissionStore from './permission';
const stores={
permissionStore
}
export default stores;
定义单文件store
import { observable, action, runInAction } from 'mobx';
import $http from '@/utils/http';
class PermissionStore {
@observable menus = [];
@action
async fetchMenus() {
try {
let menus = await this.handleFetchMenus();
runInAction(() => {
this.menus = menus;
})
} catch (error) {
}
}
handleFetchMenus() {
return $http("/permission/menuList").then(resp => {
if (resp && resp.items && resp.items.length) {
return resp.items;
}
});
}
}
export default new PermissionStore();
组件绑定
import React from 'react';
import { observer, inject } from 'mobx-react'
@inject('permissionStore');//引入对应的store
@observer
class SideMenu extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
const { permissionStore } = this.props;//从props中获取store
permissionStore.fetchMenus();//store中的异步action
}
//生成菜单栏
renderMemu = () => {
let { menus } = this.props.permissionStore;//获取状态,此时数据是异步从服务器获取后更新的数据状态
return (
...
)
}
render() {
return (
{this.renderMemu()}
)
}
}
export default SideMenu
mobx涉及的核心概念就三个,State(状态),Derivations(衍生值)和Actions(动作),使用起来非常简单和清晰,可以快速上手,是一个不错的状态管理工具,github star有21K。