怎么用視頻做網(wǎng)站登錄的背景網(wǎng)站搜索排名查詢
React redux
- 一、理解
- 1、學習文檔
- 2、redux 是什么嗎
- 3、什么情況下需要使用 redux
- 4、redux 工作流程
- 5、react-redux 模型圖
- 二、redux 的三個核心概念
- 1、action
- 2、reducer
- 3、store
- 三、redux 的核心 API
- 1、getState()
- 2、dispatch()
- 四、使用 redux 編寫應用
- 1、求和案例\_redux 精簡版
- 1.1 去除 Count 組件自身的狀態(tài)
- 1.2 src 下建立
- 1.3 store.js
- 1.4 count_reducer.js
- 1.5 在 index.js 中檢測 store 中狀態(tài)的改變,一旦發(fā)生改變重新渲染
- 2、求和案例\_redux 完整版
- 3、求和案例\_redux 異步 action 版
- 4、求和案例\_react-redux 基本使用
- 4.1 明確兩個概念
- 4.2 如何創(chuàng)建一個容器組件—— react-redux 的 connect 函數(shù)
- 4.3 備注 1:容器組件中的 store 是靠 props 傳遞的,而不是容器組件中直接引入 store
- 4.4 備注 2:mapDispatchToProps 也可以是一個對象
- 5、求和案例\_react-redux 優(yōu)化
- 6、多組件共享數(shù)據(jù)\_redux 管理
- 7、純函數(shù)
- 8、Redux 開發(fā)者工具 redux-devtool
- 五、項目打包運行
一、理解
1、學習文檔
1、英文文檔:https://redux.js.org/
2、中文文檔:http://www.redux.org.cn/
2、redux 是什么嗎
1、redux 是一個專門用于做狀態(tài)管理的 JS 庫(不是 react 插件庫)
2、它可以用在 react、angular、vue 等項目中,但基本與 react 配合使用
3、作用:集中式管理 react 應用中多個組件共享的狀態(tài)
3、什么情況下需要使用 redux
1、某個組件的狀態(tài),需要讓其他組件可以隨時拿到(共享)
2、一個組件需要改變另一個組件的狀態(tài)(通信)
3、總體原則:能不用就不用,如果不用比較吃力才考慮使用
4、redux 工作流程
將公共的數(shù)據(jù)給到 redux,
5、react-redux 模型圖
1、所有的 UI 組件都應該包裹一個容器組件,他們是父子關系。
2、容器組件時真正和 redux 打交道的,里面可以隨意的使用 redux 的 api
3、UI 組件中不能使用任何 redux 的 api
4、容器組件會傳給 UI 組件:
(1)redux 中所保存的狀態(tài)
(2)用于操作狀態(tài)的方法
5、備注:容器給 UI 傳遞:狀態(tài)(這里的狀態(tài)是 redux 中的狀態(tài))、操作狀態(tài)的方法,均通過 props 傳遞
二、redux 的三個核心概念
1、action
1、動作的對象
2、包含 2 個屬性:
type: 標識屬性,值為字符串,唯一,必要屬性
data: 數(shù)據(jù)屬性,值類型任意,可選屬性
3、例子:
{type:'ADD_STUDENT',data:{name: 'Tom', age:18}}
action
如果是 Object 的一般對象就是 同步 action
如果值是 function 的對象就是 異步 action
2、reducer
1、用于初始化狀態(tài)、加工狀態(tài)
2、加工時,根據(jù)舊的 state 和 action,產生新的 state 的純函數(shù)
3、store
1、將 state、action、reducer 聯(lián)系在一起的對象
2、如何得到此對象?
1)import {createStore} from “redux”
2)import reducer from “./reducer”
3)const store = createStore(reducer)
3、此對象的功能?
1) getState():得到 state
2)dispatch(action):分發(fā) action,觸發(fā) reducer 調用,產生新的 state
3)subscribe(listener):注冊監(jiān)聽,當產生了新的 state 時,自動調用
三、redux 的核心 API
1、getState()
獲取狀態(tài)
2、dispatch()
分發(fā)
四、使用 redux 編寫應用
求和應用
展示求和,進行 加、減、結果為奇數(shù)加、異步加 運算
1、求和案例_redux 精簡版
1.1 去除 Count 組件自身的狀態(tài)
1.2 src 下建立
-redux
-store.js
-count_reducer.js
1.3 store.js
1.3.1 引入 redux 中的 createStore 函數(shù),創(chuàng)建一個 store
1.3.2 createStore 調用時要傳入一個為其服務的 reducer
1.3.3 記得暴露 store 對象
1.4 count_reducer.js
1.4.1 reducer 的本質是一個函數(shù),接收:preState,action ,返回加工后的狀態(tài)
1.4.2 reducer 有兩個作用:初始化狀態(tài),加工狀態(tài)
1.4.3 reducer 被第一次調用時,是 store 自動觸發(fā)的:
傳遞的 preState 是 undefined
傳遞的 action 是 {type: ‘@@redux/INITn.j.9.n.r.k’}
1.5 在 index.js 中檢測 store 中狀態(tài)的改變,一旦發(fā)生改變重新渲染
備注:redux 只負責管理狀態(tài),至于狀態(tài)的改變驅動著頁面的展示,要靠我們自己寫
2、求和案例_redux 完整版
新增文件
1、count_action.js 專門用于 創(chuàng)建 action 對象
2、constant.js 放置由于編碼疏忽寫錯 action 中的 type
3、求和案例_redux 異步 action 版
1、明確:延遲的動作不想交給組件自身,想交給 action
2、何時需要異步 action:想要狀態(tài)進行操作,但是具體的數(shù)據(jù)靠異步任務返回(非必須)
3、具體編碼:
3.1 yarn add redux-thunk, 并配置在 store 中
3.2 創(chuàng)建 action 的函數(shù)不再返回一般對象,而是一個函數(shù),該函數(shù)中寫異步任務
3.3 異步任務有結果后,分發(fā)一個同步的 action 去真正操作數(shù)據(jù)
4、備注:異步 action 不是必須要寫的,完全可以自己等待異步任務的結果返回了再去分發(fā)同步 action
4、求和案例_react-redux 基本使用
4.1 明確兩個概念
1、UI 組件:不能使用任何 redux 的 api,只負責頁面的呈現(xiàn)、交互等
2、容器組件:負責和 redux 同學呢,將結果交給 UI 組件
4.2 如何創(chuàng)建一個容器組件—— react-redux 的 connect 函數(shù)
connect(mapStateToProps,mapDisapatchToProps)(UI 組件)
mapStateToProps: 映射狀態(tài),返回值是一個對象
mapDisapatchToProps:映射操作狀態(tài)的方法,返回值是一個對象
容器組件的寫法:
// 容器組件 react-redux// 引入Count 的 UI 組件
import CountUI from '../../components/Count'
// 引入 action
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction,
} from '../../redux/count_action'// 引入 connect 用于連接 UI 組件與 redux
import { connect } from 'react-redux'/*** 1、mapStateToProps 函數(shù)返回的是一個對象;* 2、返回的對象中的 key 就作為傳遞給 UI 組件 props 的key, value就作為傳遞給 UI 組件 props 的value* 3、mapStateToProps 用于傳遞狀態(tài)*/
// mapStateToProps 函數(shù)的返回值作為狀態(tài)傳遞給了 UI 組件
// 返回的對象中的 key 就作為傳遞給 UI 組件 props 的key, value就作為傳遞給 UI 組件 props 的value -- 狀態(tài)
const mapStateToProps = (state) => {return {count: state,}
}// mapDisapatchToProps 函數(shù)返回的對象中的 key 就作為傳遞給 UI 組件 props 的key, value就作為傳遞給 UI 組件 props 的value -- 操作狀態(tài)的方法
const mapDisapatchToProps = (dispatch) => {return {jia: (data) => {// 通知 redux 執(zhí)行加法dispatch(createIncrementAction(data))},jian: (data) => {// 通知 redux 執(zhí)行加法dispatch(createDecrementAction(data))},jiaAsync: (data) => {// 通知 redux 執(zhí)行加法dispatch(createIncrementAsyncAction(data, 500))},}
}// 使用 connect()() 創(chuàng)建并暴露一個 Count 的容器組件
export default connect(mapStateToProps, mapDisapatchToProps)(CountUI)
UI 組件的寫法:
import React, { Component } from 'react'
export default class CountUI extends Component {// 加法increment = () => {const { value } = this.selectNothis.props.jia(value * 1)}// 減法decrement = () => {const { value } = this.selectNothis.props.jian(value * 1)}// 當前求和為奇數(shù)再加incrementIfOdd = () => {let { count } = this.propsif (count % 2 !== 0) {this.increment()}}//異步加incrementAsync = () => {const { value } = this.selectNothis.props.jiaAsync(value * 1)}render() {console.log('props--->', this.props)return (<div><h1>當前求和為:{this.props.count}</h1><selectref={(c) => {this.selectNo = c}}><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>加</button> <button onClick={this.decrement}>減</button> <button onClick={this.incrementIfOdd}>當前求和為奇數(shù)再加</button> <button onClick={this.incrementAsync}>異步加</button></div>)}
}
4.3 備注 1:容器組件中的 store 是靠 props 傳遞的,而不是容器組件中直接引入 store
4.4 備注 2:mapDispatchToProps 也可以是一個對象
react-redux 會將 action 進行分發(fā),不再需要自己調用 dispatch
容器組件(自帶監(jiān)測功能)的優(yōu)化寫法:
// 容器組件 react-redux// 引入Count 的 UI 組件
import CountUI from '../../components/Count'
// 引入 action
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction,
} from '../../redux/count_action'// 引入 connect 用于連接 UI 組件與 redux
import { connect } from 'react-redux'// 使用 connect()() 創(chuàng)建并暴露一個 Count 的容器組件
export default connect((state) => ({ count: state }),/*// mapDispatchToProps 的一般寫法dispatch=>{return {jia: (data) =>{// 通知 redux 執(zhí)行加法dispatch(createIncrementAction(data))},jian: (data) =>{// 通知 redux 執(zhí)行加法dispatch(createDecrementAction(data))},jiaAsync: (data) =>{// 通知 redux 執(zhí)行加法dispatch(createIncrementAsyncAction(data, 500))},}}*/// mapDispatchToProps 的簡寫,{jia: createIncrementAction, // react-redux 會將action進行分發(fā),不再需要自己調用 dispatchjian: createDecrementAction,jiaAsync: createIncrementAsyncAction,},
)(CountUI)
容器組件里面的 store 從哪里得到的?——
5、求和案例_react-redux 優(yōu)化
1、容器組件和 UI 組件混成一個文件
2、無需自己給容器組件傳遞 store,給 包裹一個 Provider store={store} 即可
3、使用了 react-redux 后也不用自己監(jiān)測 redux 中狀態(tài)的改變了,容器組件可以自動完成這個工作
4、mapDispatchToProps 也可以簡單的寫成一個對象
5、一個組件要和 redux “打交道”要警告過哪幾步?
(1)定義 UI 組件 — 不暴露
(2)引入 connect 生成一個容器組件并暴露,寫法如下:
connect(state=>(key:value),// 映射狀態(tài){key: xxxxAction}//映射操作狀態(tài)的方法
)(UI 組件)
(3)在 UI 組件中通過 this.props.xxx 讀取和操作狀態(tài)
6、多組件共享數(shù)據(jù)_redux 管理
1、定義一個 Person 組件,和 Count 組件通過 redux 共享數(shù)據(jù)
2、為 Person 組件編寫:reducer、action ,配置 constant 常量
3、重點:Person 的 reducer 和 Count 的 reducer 要使用 combineReducers 進行合并,合并后的總狀態(tài)時一個對象!!!
4、交給 store 的時總 reducer,最后注意在組件中取出狀態(tài)的時候,記得“取到位”
export default connect((state) => ({sum: state.sum,personList: state.personList,}),{jia: createIncrementAction,},
)(Count)
Count 組件的 action
/*** 該文件專門為 Count 組件生成 action 對象*/
import { INCREMENT, DECREMENT } from '../constant'
export const createIncrementAction = (data) => {return {type: INCREMENT,data,}
}
// 同步 action,返回一般對象。同步 action 的值為 Object 類型的一般對象
export const createDecrementAction = (data) => ({type: DECREMENT,data,
})
// 異步action ,返回 函數(shù)。 異步action 就是指 action 的值為函數(shù)。異步action 中一般都會調用同步 action
export const createIncrementAsyncAction = (data, time) => {return (dispatch) => {console.log(dispatch, 'dispatch')setTimeout(() => {dispatch(createIncrementAction(data))}, time)}
}
// 數(shù)組和數(shù)字都不能夠開啟 異步任務,所以不會定義這些類型為異步 action
7、純函數(shù)
1、一類特別的函數(shù):只要是同樣的輸入(實參),必定得到同樣的輸出(返回)
2、必須遵守以下一些約束
(1)不得改參數(shù)數(shù)據(jù)
(2)不會產生任何副作用,例如網(wǎng)絡請求,輸入和輸出設備
(3)不能調用 Date.now() 或者 Math.random() 等不純的方法
3、redux 的 reducer 函數(shù)必須是一個純函數(shù)(不能寫 unshift 等方法添加數(shù)據(jù),如果 preState 被改寫 reducer 就不純了,頁面也不會更新)!!!
8、Redux 開發(fā)者工具 redux-devtool
1、安裝開發(fā)者工具
2、安裝依賴(配合插件使用)
npm i redux-devtools-extension
3、store 中引入
import { composeWithDevTools } from 'redux-devtools-extension'
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)),
)
store.js 完整代碼
/*** 該文件專門用于暴露一個store 對象,整個應用只有一個 store 對象*/
// 引入createStore,專門用于創(chuàng)建 redux 中最為核心的是store 對象
import { applyMiddleware, createStore, combineReducers } from 'redux'// 引入 redux-thunk 用于支持異步action
import thunk from 'redux-thunk'// 引入為 Count 組件服務的reducer
import countReducer from './reducers/count'
import personReducer from './reducers/person'
import { composeWithDevTools } from 'redux-devtools-extension'// 匯總所有的 reducer 變成一個總的 reducer
const allReducer = combineReducers({sum: countReducer,personList: personReducer,
})export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)),
)
五、項目打包運行
npm run build
使用 serve 插件可以在本地開啟一個本地服務器,使用命令 serve
就可以啟動當前的文件夾
npm i serve -g
項目資源文件