Redux状态管理
- 概念:Redux是专注于状态管理的库
- 组成:store,state,action,reducer
- 安装:
yarn add redux
- 补充:不仅仅是React,在Vue和Angular中也可以使用Redux
1,基本介绍
- store:数据源,用于存储状态(state)
- state:React中的状态,是只读对象,不可直接修改
- reducer:基本函数,用于对state的业务处理
- action:普通对象,用于描述事件的行为,改变state
2,工作流
- 用户的一个行为(比如鼠标点击)会触发Action
- Action会分发(dispatch)给Reducer
- 在Reducer中会对状态(stata)做相应的修改,并保存到数据源(STORE)中
- 组件(Component)会监听数据源(STORE)中state的变化,从而改变页面的展示内容
3,调试工具安装(可选,建议安装)
- 添加Chrome扩展程序Redux Devtools
- 安装第三方库redux-devtools-extension:
yarn add redux-devtools-extension
4,在React中使用Redux(以切换菜单为例)
- 安装react-redux插件:
yarn add react-redux
- 创建Action模块
// 文件:src/redux/action/index.js
// Action类型
export const type = {
SWITCH_MENU:'SWITCH_MENU'
}
// Action函数
// 参数:用户点击的某个菜单名称
// 返回值:对象,包括事件类型和用户点击的菜单名称的对象
export function switchMenu(menuName){
return{
type:type.SWITCH_MENU, // 事件类型
menuName // 菜单名称
}
}
- 创建Reducer模块
// 文件:src/redux/reducer/index.js
// 引入action类型
import { type } from './../action';
// 初始化state
const initialState = {
menuName:'首页',
}
// 业务处理函数
// 参数1:状态(state),参数2:动作(action)
// 返回值:对象,是一个包括所有最新state的对象
export default (state = initialState, action) => {
switch (action.type) {
// 切换菜单
case type.SWITCH_MENU:
return {
...state, // 通过对象解构的方式保留原来的所有state
menuName:action.menuName // 更新menuName
}
default:
return {
...state
};
}
}
- 创建Store模块
如果没有安装调试工具redux-devtools-extension,这样写。
// 文件:src/redux/store/index.js
// 引入reducer
import reducer from './../reducer';
// 引入createStore。这是Redux中的一个方法,用于创建一个数据源对象,保存数据
import { createStore } from 'redux';
// 导出数据源
export default () => createStore(reducer)
如果已经安装调试工具redux-devtools-extension,这样写。可以用Redux Devtools清楚地看到redux状态的变化(如果出错了,就用上一种写法,比较保险)
// 文件:src/redux/store/index.js
// 引入reducer
import reducer from './../reducer';
// 引入createStore。这是Redux中的一个方法,用于创建一个数据源对象,保存数据
import { createStore } from 'redux';
// 引入调试工具redux-devtools-extension
import { composeWithDevTools } from 'redux-devtools-extension';
// 导出数据源,可以方便地看到state变化
export default () => createStore(reducer,composeWithDevTools())
- 添加Provider作为项目的根组件,用于数据的存储
// 文件:index.js
import { Provider } from 'react-redux'; // 引入Provider组件,用于提供数据源
import configureStore from './redux/store'; // 导入数据源创建方法
const store = configureStore(); // 创建数据源
// 用Provider组件包裹根组件Router,以提供数据源
// 这样Router里面的所有组件,都可以从数据源中获取数据
ReactDOM.render(
<Provider store={store}>
<Router />
</Provider>,
document.getElementById('root'));
- 通过connect方法将React组件和Redux连接起来
更新redux的状态
import { connect } from 'react-redux'; // 引入react-redux的connect方法
import { switchMenu } from './../../redux/action'; // 引入已经定义好的action
class Sidebar extends React.Component {
// ...省略...
currentTitleManage = () => {
// ...省略...
this.props.dispatch(switchMenu(currentTitle)); // 触发switchMenu动作
// ...省略...
}
// ...省略...
}
// 通过connect方法连接Sidebar组件和redux
export default connect()(Sidebar);
取得redux的状态
import { connect } from 'react-redux';
class Header extends React.Component {
// ...省略...
{this.props.menuName} // 取得菜单名称
// ...省略...
}
// 获取数据源
const mapStateToProps = state => {
return {
menuName: state.menuName
}
}
// 通过connect方法连接Header组件和redux
export default connect(mapStateToProps)(Header);
React-router
- 安装:
yarn add react-router-dom
为什么要安装react-router-dom而不是react-router?
因为在React Router 4.0中,react-router-dom是专门用于浏览器端的路由控制器,其中已经包含了基础路由(react-router),所有我们只需要安装react-router-dom就可以了。
1,react-router和react-router-dom理解
- react-router:提供了一些router的核心api,包括Router,Route,Switch等
- react-router-dom:提供了BrowserRouter,HashRouter,Route,Link,NavLink
2,react-router-dom核心用法
-
学习网站:1213
-
HashRouter(比较常用)和BrowserRouter
HashRouter:http://localhost:3000/#/contracts/deliverCommand
BrowserRouter:http://localhost:3000/contracts/deliverCommand -
Route的用法(path,exact,component,render)
// path:路径,component:路径对应的组件
<Route path="/login" component={Login}/>
// render:添加子路由
// exact:精准匹配
<Route path='/' render={()=>
this.props.logout ?
(
<Redirect to={`/login`}/>
) :
(
<Admin>
<Switch>
<Route path="/home" component={Home}/>
<Route exact path='/contracts/list' component={ContractList}/>
...
- NavLink,Link
// NavLink:主要用于菜单导航
import { NavLink } from 'react-router-dom';
// 第一种写法:to地址
<NavLink to='/home' replace>
<span>首页</span>
</NavLink>
// 第二种写法:to对象,对象里包含一个pathname属性
<NavLink to={pathname:'/home'} replace>
<span>首页</span>
</NavLink>
// 第三种写法:to对象,对象里包含比较多的属性
<NavLink to={pathname:'/home',search:'',hash:'',key:'123',state:{}} replace>
<span>首页</span>
</NavLink>
// Link:主要用于链接
// 用法与NavLink一致
- Switch
// 单个路由匹配:如果匹配到一个路由,就结束匹配
<Switch>
<Route path="/home" component={Home}/>
<Route path='/contracts/list/add' component={ContractListDetail}/>
<Route path='/contracts/list/edit/:id' component={ContractListDetail}/>
</Switch>
- Redirect
// 路由重定向
<Redirect to='/login'/> // 重定向到login
- 嵌套子路由
// "/home"是"/"下的子路由,需要用render的形式
<Route path='/' render={()=>
<Admin>
<Switch>
<Route path="/home" component={Home}/>
</Switch>
</Admin>
}/>
// Admin组件
export default class Admin extends React.Component{
render() {
return (
<Layout style={{ minHeight: '100vh' }}>
<Sidebar/>
<Layout>
<Header/>
<Content style={{ padding: '10px 10px 0'}}>
{this.props.children} // 这里就是各个子路由对应的组件
</Content>
<Footer/>
</Layout>
</Layout>
);
}
}
网友评论