MobX 是透明的函數響應式編,它主要優勢使得狀態管理變得簡單和可擴展(這一點接下來我會簡單的對比一下redux);javascript
React 和 MobX 是一對強力組合。React 經過提供機制把應用狀態轉換爲可渲染組件樹並對其進行渲染。而MobX提供機制來存儲和更新應用狀態供 React 使用。 官網傳送二者都是狀態管理庫,用來管理應用的內部狀態,因此在咱們項目中,徹底能夠相互替代,我簡單的對比一下開發成本: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的我的看法,若有理解錯誤之處,請各位大佬指出!