Mobx工作记录

之前由于项目比较急,需要在短时间内学习并上手mobx,虽然已经用react+mobx开发了好几个项目,一直都没时间总结一下。特此梳理一下,让知识沉淀沉淀~
Mobx官方文档
Mobx官方中文文档

Mobx的核心概念

Mobx的核心原理是通过action触发state的变化,进而触发state的衍生对象(computed value & Reactions)。

1.State(状态)

其实就是我们需要用Mobx管理起来的数据。
在Mobx中,State就对应业务的最原始状态,通过observable方法,可以使这些状态变得可观察。
值得注意的一点是,当某一数据被observable包装后,他返回的是被observable包装后的类型。

2.Action(动作)

动作 是任一一段可以改变状态的代码。用户事件、后端数据推送、预定事件、等等。 动作类似于用户在excel单元格中输入一个新的值。 我们的异步请求都可以在这里做。但是这里要注意一点,异步的函数里面对state的更改是不能检测到的。所以异步的回调也需要用action()包一下:

1
2
3
4
5
6
7
8
9
10
11
12
13

class demoMobx {

@action
getServerList = (id) => {
this.send(api_url, action(res => {
// do something......
}));
}


}

这里还有一个 flow需要讲一下:

  • 用法: flow(function* (args) { }),
    flow() 接收 generator 函数作为它唯一的输入,当处理异步动作时,回调中执行的代码不会被 action 包装。这意味着你修改的 observable state 无法通过 enforceActions 检查。保留动作语义的简单方法是使用 flow 来包装异步函数。这将确保所有回调都会被 action() 包装。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { configure } from 'mobx';

// 不允许在动作外部修改状态
configure({ enforceActions: true });

class Store {
@observable githubProjects = [];
@observable state = "pending"; // "pending" / "done" / "error"


fetchProjects = flow(function* fetchProjects() { // <- 注意*号,这是生成器函数!
this.githubProjects = [];
this.state = "pending";
try {
const projects = yield fetchGithubProjectsSomehow(); // 用 yield 代替 await
const filteredProjects = somePreprocessing(projects);

// 异步代码自动会被 `action` 包装
this.state = "done";
this.githubProjects = filteredProjects;
} catch (error) {
this.state = "error";
}
})
}
3. Derivations(衍生)

这一部分的概念一直不是太理解,工作之中也不能直观的感受到它,一直迷迷糊糊。但是又感觉不影响正常开发,这里只能先留一个TODO,等啥时候脑子开窍了,再来补上吧~

:smile:

在React项目中使用Mobx

1.将store注入到全局

mobx-react 提供了 Provider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'mobx-react';
import App from './app/app';

import stores from '../../modules/store';

export function baseReact() {
return (
<Provider {...stores}>
<App/>
</Provider>
);
}

ReactDOM.render(baseReact(), document.getElementById('skin'));


2.mobx在store和组件里的应用;

mobx-react提供了rejectobserver两个工具去把store和组件关联起来。
reject 是将该组件的store注入进来;
observer可以用作包裹 React 组件的高阶组件, 在组件的 render 函数中的任何已使用的 observable 发生变化时,组件都会自动重新渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 在store.js里面引入mobx, 
import { BaseStore } from "../../../../../component.index";
import { observable, action} from "mobx";

class DesignRightStore extends BaseStore {

@observable rightComponentTabIndex: number = 0;
@observable showBackgroundColorPicker: boolean = false;

@action
setRightComponentTabIndex = (index: number) => {
this.rightComponentTabIndex = index;
}

}

export default new DesignRightStore();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// react 组件需要用到 mobx-react
import React from 'react';
import { withRouter } from "react-router";
import { inject, observer} from "mobx-react";

@withRouter
@inject('DesignRightStore') // 将DesignRightStore注入当前组件
@observer
class DesignElementPanel extends React.Component {

constructor(props){
super(props);
}

render(){
return(
<div>
{/*组件内可以通过 this.props.DesignRightStore 拿到store里面的值和方法*/}
{this.props.DesignRightStore.rightComponentTabIndex}
</div>
)
}

}

export default DesignElementPanel;