1. 前言
首先赘述一遍各个框架的官方口号
React
用于构建用户界面的
JavaScript库
Redux
Redux是JavaScript状态容器,提供可预测化的状态管理
React-Router
通过管理
URL,实现组件的切换和状态的变化
React-Thunk和React-Saga
Redux store仅支持同步数据流。使用thunk等中间件可以帮助在Redux应用中实现异步性
React通过声明式渲染和组件化很好的胜任了UI层面的工作,但是没有路由功能(管理页面之间的切换)和状态容器(管理全局数据),action中也不能执行异步操作,所以就有了react-router和redux和thunk。
2. 全家桶整合实例代码(基于Creat-React-App脚手架)
入口文件src/index.jsx
(整合redux和thunk,其中ConnectedRouter 是为了把redux中整合的router数据和react组件的router数据联系起来,不然在action里是没办法正确跳转的)
import React from "react"
import ReactDom from "react-dom"
import MyApp from "./app"
import {createStore,applyMiddleware} from "redux"
import rootReducers from "./reducer/index"
import {Provider} from "react-redux"
import reduxThunk from "redux-thunk"
import { ConnectedRouter} from 'connected-react-router'
import history from "@/actions/history";
const store = createStore(rootReducers,{},applyMiddleware(logger,reduxThunk))
ReactDom.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<MyApp/>
</ConnectedRouter>
</Provider>,
document.getElementById("app"))
redux入口文件/src/redux/index.js
(整合自己全部的reducer,同时整合history实现action里路由跳转)
import login from './login' //这里可以写自己的reducer
import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'
import history from "@/actions/history";
//history模块是为了能在action里面进行路由跳转
const reducers = combineReducers ({
router: connectRouter(history),
login,
})
export default reducers
actions文件夹下的主要文件
/src/actions/hisotry.js
import {createBrowserHistory} from 'history';
const history = createBrowserHistory()
export default history;
/src/actions/login.js
import { push } from 'react-router-redux'
export const login = ({payload}) => (dispatch) => {
//模拟登陆,异步请求后执行跳转跳转
setTimeout(() => {
dispatch(push('/home'))
}, 1000)
}
最后就是app.jsx文件(使用路由)
import React, {Fragment} from "react"
import {BrowserRouter as Router, Route, Link, NavLink, Switch,} from 'react-router-dom';
const mapStateToProps = (state) => ({
login: state.login,
})
const mapDispatchToProps = (dispatch) => ({
loginApi: (payload) => {
login(payload)(dispatch)
}
})
@withRouter
@connect(mapStateToProps, mapDispatchToProps)
export default class MyApp extends React.Component {
render() {
return (
<Fragment>
<Router>
<Switch>
//里面可以写自己的页面
</Switch>
</Router>
</Fragment>
);
}
}
看到这里是不是觉得头都大了,没错,为了把react,router,redux三者完美的联系起来,需要配置的东西太多了,严重影响开发效率。所以此时Dva和Umi等React框架就应运而生了。
3. Dva
首先老惯例还是看一下官网介绍
dva首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
光说不练假把式,我们快速创建一个dva脚手架项目看看结构
npm install dva-cli -g
dva new dva-quickstart
cd dva-quickstart
npm start
目录结构
Dva帮我们整合了很多东西,在index.js里,通过几个API就整合了router和redux
//index.js
import dva from 'dva';
import './index.css';
// 1. Initialize
const app = dva();
// 2. Plugins
// app.use({});
// 3. Model
// app.model(require('./models/example').default);
// 4. Router
app.router(require('./router').default);
// 5. Start
app.start('#root');
页面连接redux
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
function IndexPage() {
return (
<div className={styles.normal}>
</div>
);
}
IndexPage.propTypes = {
};
export default connect()(IndexPage);
而且还提出了极具规范性的model
import {routerRedux} from 'dva/router'
export default {
namespace: 'example',
state: {},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
},
},
effects: {
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save' });
yield.put(routerRedux.push('/'))
},
},
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
};
model其实就是把所有跟redux相关的一个reducer整合在一个model文件里,通过namespace区分model,通过state存储数据,通过subsciprtions实现hisotry等监听,通过effect发起异步操作,通过reducer执行同步操作,简直完美!
看来Dva已经帮我们规划好了一切,我们只要按着官网的API文档,一部一部搭建自己的应用就好了。
但是牛逼的前人们不安于现状,Umi横空出世
4. Umi 是什么?
老惯例
Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
简单来说,
Umi就是一个支持约定式路由和配置式路由的大杂烩,他整合了所有React生态的东西,Antd、Dva等等,把他们都当成了Umi的插件,我们想使用的时候,直接通过配置就能使用
再一次口说无凭,我们快速创建一个Umi脚手架项目看看结构
umi官网推荐用yarn代替npm
npm i yarn tyarn -g
mkdir myapp && cd myapp
yarn create @umijs/umi-app
yarn install
yarn start
目录结构
可以看到Umi实际上就只有
src下的一个pages文件夹(.Umi文件不用管,是项目启动之后动态构建的),内置了Dva(@umijs/plugin-dva),antd(@umijs/plugin-antd)等功能。我们只需要写页面组件就好了,简直无敌
写在最后
当然了,Dva和Umi的功能虽然强大,但是为了很好的使用他们,我们必须花更多的时间去看官网文档,重头了解他们要如何使用,如何配置。而基于Webpack构建的creat-react-app让我们有更高的自由度,实现任何功能,对习惯了webpack的人来说有种回家的感觉。