Redux狀態(tài)管理
- 概念:Redux是專注于狀態(tài)管理的庫
- 組成:store,state,action,reducer
- 安裝:
yarn add redux - 補充:不僅僅是React,在Vue和Angular中也可以使用Redux
1,基本介紹
- store:數據源,用于存儲狀態(tài)(state)
- state:React中的狀態(tài),是只讀對象,不可直接修改
- reducer:基本函數,用于對state的業(yè)務處理
- action:普通對象,用于描述事件的行為,改變state
2,工作流
- 用戶的一個行為(比如鼠標點擊)會觸發(fā)Action
- Action會分發(fā)(dispatch)給Reducer
- 在Reducer中會對狀態(tài)(stata)做相應的修改,并保存到數據源(STORE)中
- 組件(Component)會監(jiān)聽數據源(STORE)中state的變化,從而改變頁面的展示內容

image.png
3,調試工具安裝(可選,建議安裝)
- 添加Chrome擴展程序Redux Devtools
- 安裝第三方庫redux-devtools-extension:
yarn add redux-devtools-extension
4,在React中使用Redux(以切換菜單為例)
- 安裝react-redux插件:
yarn add react-redux - 創(chuàng)建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 // 菜單名稱
}
}
- 創(chuàng)建Reducer模塊
// 文件:src/redux/reducer/index.js
// 引入action類型
import { type } from './../action';
// 初始化state
const initialState = {
menuName:'首頁',
}
// 業(yè)務處理函數
// 參數1:狀態(tài)(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
};
}
}
- 創(chuàng)建Store模塊
如果沒有安裝調試工具redux-devtools-extension,這樣寫。
// 文件:src/redux/store/index.js
// 引入reducer
import reducer from './../reducer';
// 引入createStore。這是Redux中的一個方法,用于創(chuàng)建一個數據源對象,保存數據
import { createStore } from 'redux';
// 導出數據源
export default () => createStore(reducer)
如果已經安裝調試工具redux-devtools-extension,這樣寫??梢杂肦edux Devtools清楚地看到redux狀態(tài)的變化(如果出錯了,就用上一種寫法,比較保險)
// 文件:src/redux/store/index.js
// 引入reducer
import reducer from './../reducer';
// 引入createStore。這是Redux中的一個方法,用于創(chuàng)建一個數據源對象,保存數據
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'; // 導入數據源創(chuàng)建方法
const store = configureStore(); // 創(chuàng)建數據源
// 用Provider組件包裹根組件Router,以提供數據源
// 這樣Router里面的所有組件,都可以從數據源中獲取數據
ReactDOM.render(
<Provider store={store}>
<Router />
</Provider>,
document.getElementById('root'));
- 通過connect方法將React組件和Redux連接起來
更新redux的狀態(tài)
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)); // 觸發(fā)switchMenu動作
// ...省略...
}
// ...省略...
}
// 通過connect方法連接Sidebar組件和redux
export default connect()(Sidebar);
取得redux的狀態(tài)
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/deliverCommandRoute的用法(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>
);
}
}