摆脱redux繁琐操做,搭建mobx框架

简单的介绍一下mobx

MobX 是透明的函数响应式编,它主要优势使得状态管理变得简单和可扩展(这一点接下来我会简单的对比一下redux);javascript

mobx
React 和 MobX 是一对强力组合。React 经过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。 官网传送

redux和mobx对比

二者都是状态管理库,用来管理应用的内部状态,因此在咱们项目中,彻底能够相互替代,我简单的对比一下开发成本:java

这里我以标准的项目实践对比,在咱们平常项目开发中,采用redux库,下图是咱们一个业务组件的目录结构 react

一般咱们若是咱们须要经过一个接口获取列表数据,须要在多个文件中定义一整套变量,项目业务复杂开发不规范,就会出现如下现象:

反过来,咱们看下重构以后,采用mobx的文件目录结构webpack

具体实现方式,下文会详细介绍,以上仅作简单对比!git

开始搭建mobx项目

首先,该项目是采用webpack4打包器,对webpack配置不熟悉的同窗,可参考一下掘金上Better_man同窗的优秀讲解webpack4.x最详细入门讲解github

如今完事具有,只欠mobx,开始咱们的mobx之旅~web

Step 1: 安装依赖文件

npm i mobx mobx-react -D
复制代码

Step 2: 组件以及模块划分

定义好目录结构以及模块拆分很重要,使得咱们在开发过程当中思路清晰,代码整洁;npm

Step 3: 划分领域store,并定义可观察的状态

咱们在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"]
复制代码

Step 4: 建立视图以响应状态的变化

首先,在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>
        )
    }
}
复制代码

Step 5: 全局注册并注入store实例

一个常常被问到的问题就是,如何不使用单例来组合多个 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的我的看法,若有理解错误之处,请各位大佬指出!

相关文章
相关标签/搜索