react-router
redux
redux例子
01中使用webpack创建了react项目,该部分使用react-router进行路由管理,使用redux进行state管理。
使用react-router
1.安装npm install react-router-dom --save-dev
2.在src中创建router文件夹,并在其中创建index.js文件
import React from 'react';
import Home from '../pages/home/index';
import Column from '../pages/column/index';
import Analysis from '../pages/analysis/index'
import { Router, Route, Switch } from 'react-router-dom';
const history = createHashHistory();
import { createHashHistory } from "history";
class RouterConfig extends React.Component{
render(){
return(
<Router history={history}>
<Switch>
<Route path='/' exact component={Home}></Route>
<Route path="/home" component={Home}></Route>
<Home>
<Route exact path="/column" component={Column}></Route>
<Route exact path="/analysis" component={Analysis}></Route>
</Home>
</Switch>
</Router>
)
}
}
export default RouterConfig;
这里需要说明几个问题:
- switch和exact都是避免重复渲染的,这两种方法都可以唯一准确的匹配url
- 嵌套路由,将作为父页面包裹住子页面即可
3.最后将入口文件修改为
ReactDOM.render(
<div>
<RouterConfig />
</div>,
document.getElementById('root')
);
使用mock模拟后台数据
1.安装npm install mocker-api --save-dev
2.在src文件夹中创建mock文件夹,新建index.js文件以及需要引入的mock数据文件,这里的例子是menuInfo.js
3.在mock文件夹index.js中配置如下:
//引入的数据文件menuInfo.js
const menuInfo = require("./menuInfo")
const proxy = {
'GET /api/menu': menuInfo
}
module.exports = proxy
4.在webpack.config.js中devServer里添加配置
devServer: {
before (app) {
apiMocker(app, path.resolve('./src/mock/index.js'))
},
...
}
到此为止,mock就配置好了,接下来就是使用axios发送请求
使用axios发送异步请求
1.安装npm install axios --save-dev
2.在需要使用的地方引入import axios from 'axios';
即可,这部分代码后面说明
使用redux
1.安装
npm install redux --save -dev //安装redux
npm install --save react-rudex //搭配react使用
npm install redux-thunk --save-dev //使用中间件 redux-thunk
2.在src中创建store文件夹,在其中新建index.js,action.js,reducers.js,state.js
//state.js
//声明状态的默认值
export default {
homeTitle: "主页",
menuList: []
}
//actions.js
//所有的action定义
import axios from 'axios';
export function setHomeTitle (data) {
return {
type: 'SET_HOME_TITLE', //action的type值,必须
data: data //action携带的数据,非必须
}
}
export function setMenuList (list) {
return {
type: 'SET_MENU_LIST',
data: list
}
}
//异步action,中间件就是用来处理异步action的
export function getMenuList () {
return async dispatch => {
const res = await axios.get('/api/menu');
console.log(res);
if(res.status == 200) {
console.log(res.data.data.menuList);
dispatch(setMenuList(res.data.data.menuList));
}
}
}
//reducers.js
//根据action的type来返回重新计算state中的值,reducers中的函数是自动去调用的
//工具函数,用于组织多个reducer,并返回reducer集合
import { combineReducers } from 'redux';
//导入默认值
import defaultState from './state.js'
//一个reducer就是一个函数
function homeTitle (state = defaultState.homeTitle, action) {
switch (action.type) {
case 'SET_HOME_TITLE':
return action.data;
default:
return state;
}
}
function menuList (state = defaultState.menuList, action) {
switch (action.type) {
case 'SET_MENU_LIST':
return action.data;
default:
return state;
}
}
//导出所有reducer,combineReducers接收一个拆分后 reducer 函数组成的对象,返回一个新的 Reducer 函数
export default combineReducers({
homeTitle,
menuList
})
//index.js
//创建store对象
//applyMiddleware:redux通过该函数来使用中间件
//createStore:用于创建store实例
import { applyMiddleware, createStore } from 'redux';
//中间件
import thunk from 'redux-thunk';
import reducers from './reducers.js';
let store = createStore(
reducers,
applyMiddleware(thunk)
)
export default store;
3.修改入口文件
//引入provider,是react-redux两个核心工具之一(第二个connect,在组件中使用),将store传递到每个项目组件中去
import { Provider } from 'react-redux';
//引入创建好的store实例
import store from './store/index';
ReactDOM.render(
<div>
{/* 将store作为prop传入,即可使应用中的所有组件使用store */}
<Provider store={store}>
<RouterConfig />
</Provider>
</div>,
document.getElementById('root')
);
4.组件中使用
Home
import { connect } from 'react-redux';
//引入action
import { setHomeTitle, getMenuList } from '@/store/actions.js'
class Home extends Component {
constructor(props) {
super(props);
//定义state的初始值和绑定函数
this.state = {
collapsed: false,
// menuList: []
};
this.toggleCollapsed = this.toggleCollapsed.bind(this);
}
componentDidMount () {
let { setHomeTitle, getMenuList } = this.props;
setHomeTitle('hometitle');
//setMenuList();
getMenuList();
}
toggleCollapsed (){
this.setState({
collapsed: !this.state.collapsed,
});
};
render() {
//从props中解构出store
let { homeTitle, menuList } = this.props;
const menuItem = menuList.map((item) => {
//console.log(item.id)
return (
<p key={item.id}>{item.description}</p>
)
})
console.log(homeTitle)
// console.log(menuList)
return (
<div style={{ width: 256 }}>
<h1>{homeTitle}</h1>
<div>{menuItem}</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
homeTitle: state.homeTitle,
menuList: state.menuList
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
setHomeTitle (data) {
dispatch(setHomeTitle(data))
},
getMenuList () {
dispatch(getMenuList())
}
}
}
//连接store和组件
export default connect(mapStateToProps, mapDispatchToProps)(Home);