首先安装creact-react-app
npm i create-react-app -g
创建APP
create-react-app my-app
cd my-app
先执行 npm eject生成webpack配置文件
Router安装
npm i react-router -s (npm i [email protected] -s)
react-router4.0
提供了Router,Route组件
import {Router,Route} from 'react-router';
import createHashHistory from "history/createHashHistory";
<Router history={history}>
<Route path="/" component={App}></Route>
</Router>
路由嵌套 router4.0嵌套路由写在对应父组件内部
react-router3.0
import {Router,useRouterHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import {createHashHistory} from "history";
import routes from './containers/routerRegister';
import store from './store';
const routeHistory = useRouterHistory(createHashHistory)();
const history = syncHistoryWithStore(routeHistory, store);
const rootRoute = {
path:'/',
component: App,
childRoutes: routes
};
<Provider store={store}>
<Router history={history} routes={rootRoute}></Router>
</Provider>
对应的子路由childRoutes
import homeRouter from './Home/router';
import userRouter from './User/router';
const routes = []
.concat(homeRouter)
.concat(userRouter);
export default routes;
对应的子路由(如果要实现按需加载需要通过module.export导出一个模块,在routerRegister中使用require()的方式引入对应模块,在webpack中需要修改配置项,此处需要自己百度一波)
import Home from './index';
const routes = [
{
path: 'home',
component: Home,
// getComponent(nextState, cb) {
// require.ensure([], (require) => {
// cb(null, require('./EastPrescribe'))
// })
// }
}
];
export default routes;
路由传参
在router注册的页面可以使用使用this.props.router对路由进行操作,在自页面下的组件中需要使用hashHistory这个对象去调用router对用的方法,需要从react-router中引入。
import {hashHistory} from 'react-router';
this.props.router.push({
pathname:'/page',
query:{id:'123'}
// state:{id:'123'} 另外一种方式
// search: querystring.stringify({id:'123'})
});
search:需要在URL上显示的时候可以使用node.js querystring.stringify({}),这种方式可以确保URL方式进入页面时不会报参数错误
路由接受参数
this.props.location.query
this.props.location.state
querystring.parse(this.props.location.search)
redux和react-redux安装
npm i redux -s
npm i react-redux -s
npm i react-router-redux -s
npm i redux-actions -s //提供了从reactActions handleActions方法
npm i redux-promise-middleware -s //处理异步
npm i redux-logger -d
index.js
import {Provider} from 'react-redux';
import store from './store';
//设置store的作用域
<Provider store={store}></Provider>
store
import {createStore, applyMiddleware, combineReducers} from 'redux';
import {routerReducer} from 'react-router-redux';
import promiseMiddleware from 'redux-promise-middleware';
import reducers from '../reducers';
let middlewares = [];
if (process.env.NODE_ENV !== 'production') {
let createLogger = require('redux-logger').default;
middlewares.push(createLogger);
}
middlewares.push(promiseMiddleware());
export default createStore(combineReducers({
reducers,
routing: routerReducer //具体啥意思我也没有弄明白
}), applyMiddleware(...middlewares))
reducres合并对象
reducers
import { combineReducers } from 'redux';
import AppReducers from '../containers/App/reducers';
import HomeReducers from '../containers/Home/reducers';
const reducers = combineReducers({
AppReducers,
HomeReducers
});
export default reducers;
每个页面对应的actions
import {createAction} from 'redux-actions';
export const ACTION_TYPES = {
GET_INFO: "GET_INFO",
GET_DETAILS: "GET_DETAILS"
};
export const getUserInfo = createAction(ACTION_TYPES.GET_INFO, () => {
return {userName:'zhangsan'}
})
//处理异步
export const getUserInfo = createAction(ACTION_TYPES.GET_DETAILS, async (params, appId) => {
let data = await ApiService({ _mt: SYS_APIS.getPatientInfo, ...{ ...params, appId } });
return data;
});
每个页面对应的reducers
import {handleActions} from 'redux-actions';
import {ACTION_TYPES} from './actions';
const initState = {
userInfo:{},
details:{}
};
export default handleActions({
[`${ACTION_TYPES.GET_INFO}`]: (state, action)=>{
return Object.assign({}, state, {userInfo: action.payload});
},
//处理异步需要加完成状态
[`${ACTION_TYPES.GET_INFO}_FULFILLED`]: (state, action)=>{
return Object.assign({}, state, {details: action.payload});
},
}, initState);
组件中使用redux
import * as actions from './actions'; // 对应页面的actions
import { connect } from 'react-redux'; // redux绑定props的方法
import { bindActionCreators } from 'redux'; // 整合触发dispatch的方法
//将redux中的state绑定到组件的props中去
const mapStateToProps = state => {
return Object.assign({},
{
reducers: {
userInfo:state.reducers.AppReducers.userInfo
}
}
);
};
//将改变state的方法绑定到props中去
const mapDispatchToProps = (dispatch) => {
return Object.assign({}, {
actions: bindActionCreators(actions, dispatch)
});
};
//连接props和redux
export default connect(mapStateToProps, mapDispatchToProps)(App);
方法中使用redux
取值: let {reducers:{userInfo}} = this.props;
改值: this.props.actions.getUserInfo();
封装公共请求(具体处理逻辑视具体业务,主体逻辑相同)
基于axios
npm i axios -s
qs请求为post的时候使用formData方式请求
npm i qs -s
定义返回code枚举 (api网关通用异常code)
const STATUS_CODE = {
'-120': '错误1',
'-140': '错误2',
'-180': '错误3',
...
}
处理全局错误拦截
//===全局错误处理 BEGIN ===//
axios.interceptors.response.use(
response => {
'use strict';
let {data: { stat }, config } = response;
if (config.url === Settings.API) {
let errorMsg = '';
if (stat.code !== 0 || stat.stateList[0].code !== 0) {
errorMsg = STATUS_CODE[stat.code] || STATUS_CODE[stat.stateList[0].code] || '系统服务异常, 请稍后重试';
//登录态异常,引导重新登录
if (stat.code === -300){
// appRelogin();
}else if (stat.code === -320 || stat.code === -340 || stat.code === -180 || stat.code === -360){
// appLogin();
}
}
if (errorMsg){
Toast.info(errorMsg);
return Promise.reject(config.params._mt+':'+errorMsg);
}
}
return response;
},
error => {
'use strict';
return Promise.reject(error);
}
);
//===全局错误处理 END ===//
网关请求接口
export default function ApiService(params, userLogin = true, options = {}, externConfig = {silent:false}) {
if (!params || typeof params !== 'object') {
throw new Error('params is not an object.');
}
if (!params.hasOwnProperty('_mt') || !params['_mt']) {
throw new Error('Miss "_mt"');
}
let encryptedParams = encrypt(params, userLogin);
let config = Object.assign({}, {
url: Settings.API,
method: 'get',
withCredentials: true
}, options);
//post情况下, 以form data模式传递数据
if (config.method.toLowerCase() === 'post') {
config.headers = Object.assign({}, (config.headers || {}), { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' });
config.params = Object.assign({}, (config.params || {}), { _mt: encryptedParams._mt });
delete encryptedParams._mt;
config.data = qs.stringify(encryptedParams, { arrayFormat: 'brackets' });
} else {
config.params = encryptedParams;
}
return axios(config).then(res => {
let data = res.data;
if (data.content && data.content[0] && data.content[0].hasOwnProperty('success') && !data.content[0].success) {
//业务接口异常提示
let errorMsg = data.content[0].errorMsg;
if(!externConfig.silent) {
errorMsg&&Toast.info(errorMsg);
}
return Promise.reject(data.content[0]);
} else {
return data.content && res.data.content[0] && res.data.content[0].value ? res.data.content[0].value : res.data
}
});
}
架构目录