Mobx是一种前端数据流方案,相较于redux,它对数据的处理显得更加的简洁,更加符合store增删查改的的操作概念。MobX通过透明的函数响应式编程使得状态管理变得简单和可扩展。
(官方)MobX背后的哲学很简单:
任何源自应用状态的东西都应该自动地获得。
流程图:(接下来将会一一介绍以下功能)
一、安装
安装: npm install mobx --save。 React 绑定库: npm install mobx-react --save。 要启用 ESNext 的装饰器 (可选), 参见下面。
CDN:
https://unpkg.com/mobx/lib/mobx.umd.js
https://cdnjs.com/libraries/mobx
二、 Observable state
MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。
通过使用 @observable 装饰器实现。@observable可以在字段和属性getter上使用,提供了更加细粒度的控制。
例子:
import { observable } from "mobx";
class Todo {
id = Math.random();
@observable title = "";
@observable finished = false;
}
示例:
import {observer} from "mobx-react";
var timerData = observable({
secondsPassed: 0
});
setInterval(() => {
timerData.secondsPassed++;
}, 1000);
@observer class Timer extends React.Component {
render() {
return (<span>Seconds passed: { this.props.timerData.secondsPassed } </span> )
}
};
ReactDOM.render(<Timer timerData={timerData} />, document.body);
observer 函数/装饰器可以用来将 React 组件转变成响应式组件。 它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。
注意: 当 observer 需要组合其它装饰器或高阶组件时,请确保 observer 是最深处(第一个应用)的装饰器,否则它可能什么都不做。
三、 Computed values
通过@computed 装饰器,可以在定义相关数据发生变化时自动更新。计算值是可以根据现有的状态或其它计算值衍生出的值。 概念上来说,它们与excel表格中的公式十分相似。
如果任何影响计算值的值发生变化了,计算值将根据状态自动进行衍生。 计算值在大多数情况下可以被 MobX 优化的,因为它们被认为是纯函数。
注意:它是用来计算得到值,不能用来改变状态值。
四、 Reactions
Reactions 和计算值很像,但它不是产生一个新的值,而是会产生一些副作用,比如打印到控制台、网络请求、递增地更新 React 组件树以修补DOM、等等。
六、 自定义reactions
使用autorun、reaction 和 when 函数即可简单的创建自定义 reactions,以满足你的具体场景。
例子:
例如,每当 unfinishedTodoCount 的数量发生变化时,下面的 autorun 会打印日志消息:
autorun(() => {
console.log("Tasks left: " + todos.unfinishedTodoCount)
})
七、 Actions
任何应用都有action。action是任何用来修改状态的东西。应该永远只对修改状态的函数使用动作。 只执行查找,过滤器等函数不应该被标记为动作,以允许 MobX 跟踪它们的调用。
示例:
class Ticker {
@observable tick = 0
@action.bound
increment() {
this.tick++ // 'this' 永远都是正确的
}
}
const ticker = new Ticker()
setInterval(ticker.increment, 1000)
编写异步 Actions
action 包装/装饰器只会对当前运行的函数作出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应! 这意味着如果 action 中存在 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。
示例:
mobx.configure({ enforceActions: true }) // 不允许在动作之外进行状态修改
class Store {
@observable githubProjects = []
@observable state = "pending" // "pending" / "done" / "error"
@action
fetchProjects() {
this.githubProjects = []
this.state = "pending"
fetchGithubProjectsSomehow().then(
projects => {
const filteredProjects = somePreprocessing(projects)
this.githubProjects = filteredProjects
this.state = "done"
},
error => {
this.state = "error"
}
)
}
}
上面的示例会抛出异常,因为传给 fetchGithubProjectsSomehow promise 的回调函数不是 fetchProjects 动作的一部分,因为动作只会应用于当前栈。
正确写法:
mobx.configure({ enforceActions: true })
class Store {
@observable githubProjects = []
@observable state = "pending" // "pending" / "done" / "error"
@action
fetchProjects() {
this.githubProjects = []
this.state = "pending"
fetchGithubProjectsSomehow().then(this.fetchProjectsSuccess, this.fetchProjectsError)
}
@action.bound
fetchProjectsSuccess(projects) {
const filteredProjects = somePreprocessing(projects)
this.githubProjects = filteredProjects
this.state = "done"
}
@action.bound
fetchProjectsError(error) {
this.state = "error"
}
}
八、 资料分享
中文教程:https://cn.mobx.js.org/
API:https://cn.mobx.js.org/refguide/api.html