整合react + mobx + axios + react-router4
react + mobx + axios + react-router4

一,定义axios的api接口
aService.js
import axios from 'axios';
const errorHandler = error => {
console.log("出错信息如下");
console.log(error);
}
const host = 'http://www.example.com';
export default {
getList(){
return axios.get(`${host}/api/XXX`).catch(errorHandler);//get, post, put, delete方法都有
},
getDetail(id) {
return axios.get(`${host}/api/XXX?id=${id}`).catch(errorHandler);
}
}
//bService.js 同理
二,定义mobx数据仓库
原则上一个页面级组件及其的子组件都公用一个实例化的数据仓库
AStore.js
import { observable, action, toJS, computed } from 'mobx';
import aService from 'aService';
/**
* A 自己的store
* 在 页面级 通过 Provider 渗透到所有子组件。
* 在子组件内用 @inject('store'),将 store 注入到自己的 props 上。
*/
class Store {
constructor() {
this.getListForApi = this.getListForApi.bind(this);
}
@observable list = []; //被观察的属性数据
@computed get getList(){ return toJS(this.list) } //get方法, 把observer类型转为js的类型返回
@action.bound setList(value) { this.list = value; } //set方法
getListForApi(){
aService.getList().then(this.getListForApiCallBack);
}
@action.bound getListForApiCallBack(res){
//这里的api回调必须这样分开写才可以被观察到
//这里调用api,拿到后台返回的数据后,把list赋值
}
}
export default new Store
// 导出一个new的Store,确保渗透的数据仓库都用同一份数据,同一个实例
ADetailStore.js
import { observable, action, toJS, computed } from 'mobx';
import aService from 'aService';
class Store {
constructor() {
this.getDetailForApi = this.getDetailForApi.bind(this);
}
@observable id = '';
@computed get getId(){ return toJS(this.id) } //get方法
@action.bound setId(value) { this.id = value; } //set方法
@observable info = {
name: '',
code: '',
get getName(){ return toJS(this.name) },
setName(value){ this.name = value; },
get getCode(){ return toJS(this.code) },
setCode(value){ this.code = value; }
}
getDetailForApi(){
aService.getDetail(this.getId).then(this.getDetailForApi);
}
@action.bound getDetailForApiCallBack(res){
//todo
}
}
export default new Store
三,定义页面级组件
A.js
import React from 'react';
import PropTypes form 'prop-types';
import { observer, Provider } from 'mobx-react';
import store from 'AStore';
import { withRouter } from 'react-router-dom';
@withRouter //可获取路由信息并且有改变路由的权限
class A extends React.Component{
constructor(props) {
super(props);
}
render(){
return (
<div>
<ul>
{store.getList.map((item, i)=>
<li key={i}>{item.name}</li>
)} //获取store的数据并且循环渲染
</ul>
<button
onClick={()=>this.props.history.push('/a/123')} //跳转到A的详情页面并且附带参数值123
></buton>
</div>
)
}
}
A.propTypes = {
name: PropTypes.string.isRequired
}
A.defaultProps = {name: ''}
export default A;
//B同理
//用了mobx的数据仓库可以用全局的数据来控制,用引进的store做数据仓库propTypes和defaultProps可不写
ADetail.js
import React from 'react';
import PropTypes form 'prop-types';
import { observer, Provider } from 'mobx-react';
import store from 'ADetailStore';
import { withRouter } from 'react-router-dom';
@withRouter
class ADetail extends React.Component{
constructor(props) {
super(props);
}
componentDidMount() {
store.getDetailForApi();
}
render(){
return (
<Provider store={store}>
<div>
ID参数值 是{this.props.match.params.id}
//这里可以显示和调用store的方法和数据
</div>
</Provider>
)
}
}
export default ADetail;
//BDetail同理
ADetailComponent.js
import React from 'react';
import { observer, inject } from 'mobx-react';
@inject('store') //inject写在observer之前
@observer //检测页面随着检测的数据变化而发生变化
class ADetailComponent extends React.Component{
constructor(props) {
super(props);
}
render(){
return (
<div >
名称 : {this.props.store.info.getName}
//这里可以显示和调用父层组件(不限)ADetail渗透进来的store的方法和数据
</div>
)
}
}
export default ADetailComponent;
Error404.js
import React from 'react';
class Error404 extends React.Component{
render(){
return (
<div >
404页面
</div>
)
}
}
export default Error404;
四,定义路由配置文件
routersConfig.js
//配置不用写登录页和404这种特殊页面,只写菜单导航页即可
import A from 'A';
import ADetail from 'ADetail';
import B from 'B';
import BDetail from 'BDetail';
export default
[{
'path': '/a',
'component': A,
'meta': {} //这里是自定义的信息。可写可不写
},{
'path': '/a/:id', //这里是id是必传的参数如 /a/123
'component': ADetail
},{
'path': '/b',
'component': B
},{
'path': '/b/:id?', //这里是id是非必传的参数如 /a/123 或者 /a 都不会报错
'component': BDetail,
},]
五,定义路由入口文件
一级路由index.js
import React, { Component } from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import LoginPage from 'LoginPage';
import MainPage from 'MainPage';
@withRouter
class Index extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
//判断是否已登录
}
componentWillReceiveProps() {
//判断是否已登录
}
render (){
return (
<div>
<Switch>
<Route path="/login" component={LoginPage} />
<Route path='/' component={MainPage} />
</Switch>
</div>
)
}
}
export default Index
二级路由MainPage.js
import React, { Component } from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import routerConfig from 'routerConfig'; //导入路由配置文件作遍历
import Error404 from 'Error404';
class MainPage extends Component {
constructor(props) {
super(props);
}
render (){
return (
<div>
<NavComponent />
<MainContent />
</div>
)
}
}
//导航组件
class NavComponent extends Component {
render (){
return (
<div>
</div>
)
}
}
//页面主组件
@withRouter
class MainContent extends Component {
render (){
return (
<div>
<Switch>
{routerConfig.map((item, i) =>
<Route key={i} path={item.path} exact render={props =>
<item.component collapsed={this.props.collapsed} changeCollapsed= {this.props.changeCollapsed} meta={item.meta} />
} >
</Route>
)}
<Route exact component={Error404}></Route>
</Switch>
</div>
)
}
}
export default MainPage