MobX 是透明的函数响应式编,它主要优势使得状态管理变得简单和可扩展(这一点接下来我会简单的对比一下redux);javascript
二者都是状态管理库,用来管理应用的内部状态,因此在咱们项目中,彻底能够相互替代,我简单的对比一下开发成本:java
这里我以标准的项目实践对比,在咱们平常项目开发中,采用redux库,下图是咱们一个业务组件的目录结构 react
反过来,咱们看下重构以后,采用mobx的文件目录结构webpack
具体实现方式,下文会详细介绍,以上仅作简单对比!git
首先,该项目是采用webpack4打包器,对webpack配置不熟悉的同窗,可参考一下掘金上Better_man同窗的优秀讲解webpack4.x最详细入门讲解!github
如今完事具有,只欠mobx,开始咱们的mobx之旅~web
npm i mobx mobx-react -D
复制代码
定义好目录结构以及模块拆分很重要,使得咱们在开发过程当中思路清晰,代码整洁;npm
咱们在store文件夹下新建,movieStore.js文件,以下图redux
接下来,如何定义可观察的状态呢,咱们看代码:api
import {observable, action, computed, runInAction} from 'mobx';
import Api from '../api/movie';
export class movieStore {
@observable movieList = [];
@observable state = 'pending';
constructor(rootStore) {
this.rootStore = rootStore;
this.fetchMovies = this.fetchMovies.bind(this);
this.setPrice = this.setPrice.bind(this);
}
@action
async fetchMovies() {
this.state = 'pending';
this.movieList = [];
try {
const subjects = await Api.getMovie();
//await以后更改状态
runInAction(() => {
this.state = 'Done';
this.movieList = subjects;
});
} catch (e) {
runInAction(() => {
this.state = "error";
});
}
}
}
复制代码
上面咱们定义了2个状态,movieList:电影列表,state: 接口的请求状态,在其变量前面加上@observable 使其可观察,同时定义action,请求接口并改变初始状态,以上代码写法须要开启装饰器,(1)添加装饰器依赖
npm i babel-plugin-transform-decorators-legacy -D
复制代码
(2).babelrc文件添加配置
"plugins": ["transform-decorators-legacy"]
复制代码
首先,在views目录下,新建movie文件来存放movie组件相关文件,在movie文件夹下建立index.jsx, 定义observer包裹React组件的高级组件
import React, {Component} from 'react';
import {observer} from "mobx-react";
@observer
export default class Movie extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>movie</div>
)
}
}
复制代码
一个常常被问到的问题就是,如何不使用单例来组合多个 stores 。它们之间如何通讯呢? 答案就是,建立一个 RootStore 来实例化全部 stores ,并共享引用; 示例: store/index.js
import {configure, observable, computed} from 'mobx';
import {movieStore} from './movieStore';
import {loginStore} from './loginStore';
configure({enforceActions: 'observed'});
export default class store {
@observable movieStore;
@observable loginStore;
constructor() {
this.movieStore = new movieStore(this);
this.loginStore = new loginStore(this);
}
}
复制代码
完成多个领域store的组合,使用
<Provider rootStore={new RootStore()}><App /></Provider>
复制代码
方式注入到组件库中。接下来就是在咱们的视图组件中引入单个store,视角再次切换回到Movie组件,完善代码:
import React, {Component} from 'react';
import {inject, observer} from "mobx-react";
import { Table } from 'antd';
@inject((stores) => {
return {
movieStore: stores.store.movieStore
}
})
@observer
export default class Movie extends Component {
constructor(props) {
super(props);
}
async componentDidMount(){
const {movieList,fetchMovies} = this.props.movieStore;
if (movieList.length > 0)
return;
await fetchMovies();
}
render() {
const {state, movieList, setPrice, price} = this.props.movieStore;
const columns = [{
title: '名称',
dataIndex: 'title',
render: text => <a href="javascript:;">{text}</a>,
}, {
title: '豆瓣评分',
dataIndex: 'rating',
}, {
title: '年份',
dataIndex: 'year',
}, {
title: '描述',
dataIndex: 'original_title'
}];
const data = movieList.map(item => ({
id: item.id,
key: item.id,
title: item.title,
rating: item.rating.average,
year: item.year,
original_title: item.original_title
}));
return (
<div>
<Table loading={state === 'pending'} columns={columns} dataSource={data} />
</div>
)
}
}
复制代码
经过@inject,注入咱们须要的store,注入以后咱们能够在组件props中访问可观察属性和方法; 这里我使用antd UI库的table组件做为数据展现,有兴趣可去Ant Design官网
以上是简单的mobx项目搭建,项目源代码请戳react-mobx,新手上路,以上都属于本身学习mobx的我的看法,若有理解错误之处,请各位大佬指出!