原文链接: https://notes.hejian.tech/p/2018/learn-mobx-md/
前端数据流方案 Mobx
一个简介易用的 前端数据流和状态管理库
说到 react 的数据流和状态管理, 我们 都知道 redux、flux
而 Mobx 则是 精髓版的 redux、flux
搬一下笔记
闲聊聊
12 月的北京,凌晨 3 点的龙泽,泡杯绿茶,抱着电脑蜷缩在被窝,思考的都是今天写多少代码可以换来房租,明天尝试接个项目可以换多少天的生活费,理想离我越来越远。
Mobx
介绍
Mobx 是一个 前端数据流状态管理库,react 好伙伴。
具体作用 和 redux、flux 差不多, 但是更清爽易用。
它通透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展。
MobX 背后的哲学
任何源自应用状态的东西都应该自动地获得。
核心概念
5 个 核心概念
Observable state(可观察的状态)
MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。
状态 是驱动应用的数据。 通常有像待办事项列表这样的领域特定状态,还有像当前已选元素的视图状态。 记住,状态就像是有数据的 excel 表格。
通过使用 @observable 装饰器(ES.Next)来给你的类属性添加注解就可以简单地完成这一切。
记得 之前 看 angular7 ,有 Observable(可观察对象),但似乎只是名字像,记得 Angular 7 默认状态管理是 RxJs, 其中的 Observable 可以发送 任意多值,而且呢,被订阅之前,不会被执行
支持 ES6 装饰器写法,简洁
import { observable } from "mobx";
class Todo {
id = Math.random();
@observable title = "";
@observable finished = false;
}
ES5 版写法
import { decorate, observable } from "mobx";
class Todo {
id = Math.random();
title = "";
finished = false;
}
decorate(Todo, {
title: observable,
finished: observable,
});
Derivations(衍生)
任何 源自状态并且不会再有任何进一步的相互作用的东西就是衍生。 衍生以多种形式存在:
- 用户界面
- 衍生数据,比如剩下的待办事项的数量。
- 后端集成,比如把变化发送到服务器端。
MobX 区分了两种类型的衍生:
- Computed values(计算值) - 它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值。
- Reactions(反应) - Reactions 是当状态改变时需要自动发生的副作用。需要有一个桥梁来连接命令式编程(imperative programming)和响应式编程(reactive programming)。或者说得更明确一些,它们最终都需要实现 I / O 操作。
刚开始使用 MobX 时,人们倾向于频繁的使用 reactions。 黄金法则: 如果你想创建一个基于当前状态的值时,请使用 computed。
Computed values(计算值)
使用 MobX, 你可以定义在相关数据发生变化时自动更新的值。 通过@computed 装饰器或者利用 (extend)Observable 时调用 的 getter / setter 函数来进行使用。(当然,这里也可以再次使用 decorate 来替代 @ 语法)。
class TodoList {
@observable todos = [];
@computed get unfinishedTodoCount() {
return this.todos.filter(todo => !todo.finished).length;
}
}
当添加了一个新的 todo 或者某个 todo 的 finished 属性发生变化时,MobX 会确保 unfinishedTodoCount 自动更新。 像这样的计算可以类似于 MS Excel 这样电子表格程序中的公式。每当只有在需要它们的时候,它们才会自动更新。
Reactions(反应)
Reactions 和计算值很像,但它不是产生一个新的值,而是会产生一些副作用,比如打印到控制台、网络请求、递增地更新 React 组件树以修补 DOM、等等。 简而言之,reactions 在 响应式编程和命令式编程之间建立沟通的桥梁。
(React)组件
如果你用 React 的话,可以把你的(无状态函数)组件变成响应式组件,方法是在组件上添加 observer 函数/ 装饰器. observer 由 mobx-react 包提供的。
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {observer} from 'mobx-react';
@observer
class TodoListView extends Component {
render() {
return <div>
<ul>
{this.props.todoList.todos.map(todo =>
<TodoView todo={todo} key={todo.id} />
)}
</ul>
Tasks left: {this.props.todoList.unfinishedTodoCount}
</div>
}
}
const TodoView = observer(({todo}) =>
<li>
<input
type="checkbox"
checked={todo.finished}
onClick={() => todo.finished = !todo.finished}
/>{todo.title}
</li>
)
const store = new TodoList();
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'));
Actions(动作)
动作 是任一一段可以改变状态的代码。用户事件、后端数据推送、预定事件、等等。 动作类似于用户在excel单元格中输入一个新的值。
在 MobX 中可以显式地定义动作,它可以帮你把代码组织的更清晰。 如果是在严格模式下使用 MobX的话,MobX 会强制只有在动作之中才可以修改状态。
与 Flux 等框架不同,Mobx 对于如何处理用户事件是 完全透明 的
- 可以用类似 Flux 的方式完成
- 或者使用 RxJS 来处理事件 (对 有过 angular 开发经验的小伙伴非常友好)
- 或者用最直观、最简单的方式来处理事件,正如上面演示所用的 onClick
原则
MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。
import {observable, autorun} from 'mobx';
var todoStore = observable({
/* 一些观察的状态 */
todos: [],
/* 推导值 */
get completedCount() {
return this.todos.filter(todo => todo.completed).length;
}
});
/* 观察状态改变的函数 */
autorun(function() {
console.log("Completed %d of %d items",
todoStore.completedCount,
todoStore.todos.length
);
});
/* ..以及一些改变状态的动作 */
todoStore.todos[0] = {
title: "Take a walk",
completed: false
};
// -> 同步打印 'Completed 0 of 1 items'
todoStore.todos[0].completed = true;
// -> 同步打印 'Completed 1 of 1 items'