阅读时间:大概在 3 分钟左右
本文章旨在介绍Mobx,不对其他状态管理工具进行比较。
Redux 开启了前端状态管理大门,但是对于一些比较小的应用,使用 Redux 反而增加了开发复杂度,这时候,我会选择使用 Mobx 来进行状态管理。
Mobx 是什么
Mobx是一个通过函数响应式编程,让状态管理更加简单和容易拓展的库。
它遵循一个最简单的原则:
Anything that can be derived from the application state, should be derived. Automatically.
(所有能够从应用状态获得的东西,都应该自动地被获得)
他的原理非常简洁:
- Actions 是唯一允许修改state而且有其他副作用的函数
- State 是一组可观察的状态,而且不应该包含冗余的数据(例如不会被更新的状态)
- Computed Value 是一些纯函数,返回通过 state 可以推导出的值
- Reactions 类似于 Computed Value,但是它允许副作用的产生(如更新 UI 状态)
核心概念
Observable state
Mobx 为 JavaScript 本身已有的几种数据结构都添加了可观察的功能,也可以使用ES6的新特性,通过装饰器来添加这些功能。
可观察的对象:
import {observable, autorun, action} from "mobx";
var person = observable({
// 可观察的属性
name: "John",
age: 42,
showAge: false,
// 计算后的属性
get labelText() {
return this.showAge ? `${this.name} (age: ${this.age})` : this.name;
},
// action
setAge: action(function(age) {
this.age = age;
})
});
// autorun 函数是来运行状态后更新后引发的 reaction
autorun(() => console.log(person.labelText));
person.name = "Dave";
// 输出: 'Dave'
复制代码
可观察的数组:
import {observable, autorun} from "mobx";
var todos = observable([
{ title: "Spoil tea", completed: true },
{ title: "Make coffee", completed: false }
]);
autorun(() => {
console.log("Remaining:", todos
.filter(todo => !todo.completed)
.map(todo => todo.title)
.join(", ")
);
});
todos[0].completed = false;
// 输出: 'Remaining: Spoil tea, Make coffee'
todos[2] = { title: 'Take a nap', completed: false };
// 输出: 'Remaining: Spoil tea, Make coffee, Take a nap'
todos.shift();
// 输出: 'Remaining: Make coffee, Take a nap'
复制代码
可观察的Map:
import {observable} from "mobx";
const map = observable.map();
map.set("a", 100);
console.log(map.get("a"))
// 输出: 100
map.observe(({name, newValue}) => console.log(name, "->", newValue))
map.set("b",100)
// 输出: b -> 100
复制代码
原生的值和引用:
import {observable} from "mobx";
const cityName = observable("Vienna");
console.log(cityName.get());
// 输出 'Vienna'
cityName.observe(function(change) {
console.log(change.oldValue, "->", change.newValue);
});
cityName.set("Amsterdam");
// 输出 'Vienna -> Amsterdam'
复制代码
Actions
状态管理中有一个重要的概念,状态应该以一种方式来更新。在Mobx之中,并不需要触发事件、调用分发函数或者类似的动作,状态的基本相应派发由 Mobx 本身来负责。
但是让Mobx全盘接管显然限制了可拓展性和可用性,所以Mobx提供了Actions来使用。Actions应该永远只对修改状态的函数使用动作。建议对任何修改 observables 或具有副作用的函数使用 (@)action
。 结合开发者工具的话,动作还能提供非常有用的调试信息。
Reactions
Reactions 和计算值很像,但它不是产生一个新的值,而是会产生一些副作用,比如打印到控制台、网络请求、递增地更新 React 组件树以修补DOM、等等。 简而言之,reactions 在 响应式编程和命令式编程之间建立沟通的桥梁。
在 React 里使用 Mobx
谈了那么多概念那么怎么在 React 里面使用呢。
observer
函数/装饰器可以用来将 React 组件转变成响应式组件。 它用 mobx.autorun
包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。 observer
是由单独的 mobx-react
包提供的。
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> )
}
};
React.render(<Timer timerData={timerData} />, document.body);
复制代码
mobx 使用的时候,确保让observer渗透到最深处的组件,因为状态是向下传递的,如果原子组件没有加入Mobx的观察,那么就可能就没有效果。
拓展阅读