??????
??個(gè)人主頁(yè): 阿選不出來
??????
??個(gè)人簡(jiǎn)介: 一名大二在校生,學(xué)習(xí)方向前端,不定時(shí)更新自己學(xué)習(xí)道路上的一些筆記.
??????
??目前開發(fā)的專欄: JS ??Vue??React??
??????
Redux理解
Redux 是 JavaScript 狀態(tài)容器,提供可預(yù)測(cè)化的狀態(tài)管理。
redux是什么
- redux是一個(gè)專門用于做狀態(tài)管理的JS庫(kù)(不是react插件庫(kù))。
- 它可以用在react,angular,vue等項(xiàng)目中,但基本與react配合使用。
- 作用:集中式管理react應(yīng)用中多個(gè)組件共享的狀態(tài)。
redux的使用場(chǎng)景
- 某個(gè)組件的狀態(tài),需要讓其他組件可以隨時(shí)拿到(共享)。
- 一個(gè)組件需要改變另一個(gè)組件的狀態(tài)(通信)。
- 總體原則:能不用就不用,如果不用比較吃力才考慮使用。
redux的三大原則
- state以單一對(duì)象存儲(chǔ)在store對(duì)象中
- state只讀(每次都返回一個(gè)新的對(duì)象)
- 使用純函數(shù)reducer執(zhí)行state更新
redux基本使用
下載redux包
npm i redux
代碼結(jié)構(gòu)
store.js文件專門用于創(chuàng)建并配置store并暴露
//引入createstore,用于創(chuàng)建store對(duì)象
import {legacy_createStore as createStore} from 'redux'
// 引入reducer
import reducer from './reducers'
const store = createStore(reducer)
export default store
actions文件夾存放多個(gè)為指定組件生成的action對(duì)象。
reducers文件夾存放多個(gè)為指定組件服務(wù)的reducer純函數(shù)。
constant.js文件用于定義action對(duì)象中type類型的常量值,便于管理,防止單詞的拼寫錯(cuò)誤。
例:
export const INCREMENT = 'increment'
Redux的三個(gè)核心概念
Redux的工作流
- View在redux中會(huì)派發(fā)action方法
- action通過store的dispatch方法會(huì)派發(fā)給store
- store接收action,連同之前的state,一起傳遞給reducer
- reducer返回新的數(shù)據(jù)給store
- store去改變自己的state
1.action
Action 是把數(shù)據(jù)從應(yīng)用(譯者注:這里之所以不叫 view 是因?yàn)檫@些數(shù)據(jù)有可能是服務(wù)器響應(yīng),用戶輸入或其它非 view 的數(shù)據(jù) )傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來源。一般來說你會(huì)通過 store.dispatch()
將 action 傳到 store。
const ADD_TODO = 'ADD_TODO'
{
type: ADD_TODO,
data: 'Bilid my first Redux app'
}
action本質(zhì)為JavaScript普通對(duì)象。
action內(nèi)必須包含 type
屬性,值為字符串,表示將要執(zhí)行的動(dòng)作,作為唯一標(biāo)識(shí)。
除 type
屬性外,action對(duì)象的結(jié)構(gòu)完全由你自己決定,通常會(huì)傳入 data
屬性,值為某個(gè)組件向reducer函數(shù)操作state時(shí)傳的參數(shù)。
在模塊化開發(fā)中,一個(gè)組件可能會(huì)需要多個(gè)action對(duì)象,通常按照下方的寫法。
const INCREMENT = 'INCREMENT'
export const increment = data =>({type: INCREMENT,data})
...
異步action
例如:點(diǎn)擊一個(gè)按鈕,三秒后讓一個(gè)count
數(shù)值加一。
當(dāng)點(diǎn)擊按鈕后,組件內(nèi)通過 store.dispatch
將action對(duì)象派發(fā)給store。
我們?cè)赼ction中返回一個(gè)定時(shí)器,3秒后調(diào)用同步action觸發(fā) dispatch
執(zhí)行加動(dòng)作。
export const incrementAsync = (data,time) =>{
return (dispatch)=>{
setTimeOut(()=>{
dispatch(increment(data))
})
}
}
由于redux本身不支持異步操作。react給我們提供了一個(gè)插件 redux-thunk 可以讓redux擁有異步操作的能力。
用法:
store.js文件下
import {legacy_createStore as createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk
...
export default createStore(reducer,applyMiddleware(thunk))
2.reducer
reducer用于將store發(fā)過來的action完成并將結(jié)果返回給store,他有兩個(gè)作用:初始化store和更新store。
reducer接收兩個(gè)參數(shù)preState(舊狀態(tài))和action(動(dòng)作)并返回一個(gè)newState(新狀態(tài))。
(previousState, action) => newState
初始化狀態(tài)
const initState = 0 //初始化狀態(tài)
reducer純函數(shù)
function count(preState=initState,action){
// 從actions對(duì)象中獲?。簍ype,data
const {type,data} = action
//根據(jù)type決定如何加工數(shù)據(jù)
switch(type){
case INCREMENT:
return xxx
...
default:
return preState
}
}
注意:redux的reducer是一個(gè)純函數(shù)。純函數(shù)是一類特別的函數(shù)。
純函數(shù)的規(guī)則:
- 不能改寫參數(shù)數(shù)據(jù)。
- 不會(huì)產(chǎn)生任何副作用,例如網(wǎng)絡(luò)請(qǐng)求,輸入和輸出設(shè)備。
- 不能調(diào)用Date.now()或Math.random()等不純的方法。
例如:當(dāng)我們要對(duì)store里的一個(gè)數(shù)組添加一個(gè)對(duì)象時(shí):
錯(cuò)誤的寫法:
preState.unshift(data)
此時(shí),preState這個(gè)實(shí)參被改寫了,reducer不在是純函數(shù)。
正確的寫法:
使用對(duì)象展開運(yùn)算符
[data,...preState]
創(chuàng)建了一個(gè)新數(shù)組。
combineReducers
Redux應(yīng)用中只有一個(gè)單一的store。當(dāng)多個(gè)組件都需要用到store時(shí),便于數(shù)據(jù)邏輯處理,我們需要使用reducer組合。
redux提供了 combineReducers()
工具類,組合多個(gè)reducer。
import {combineReducers} from 'redux'
//引入多個(gè)reducer
import reducer1 from './reducer1'
import reducer2 from './reducer2'
...
export default combineReducers({
reducer1,
reducer2
})
3.store
前文我們知道了使用action
描述“發(fā)生了什么”,使用 reducers
來根據(jù)action更新state的用法。
而 store 就是action 和 reducer 之間的橋梁。
store的創(chuàng)建
//引入createstore,用于創(chuàng)建store對(duì)象
import {legacy_createStore as createStore} from 'redux'
// 引入reducer
import reducer from './reducers'
const store = createStore(reducer)
createStore第一個(gè)參數(shù)傳入reducer,第二個(gè)參數(shù)為可選的,用于設(shè)置state初始狀態(tài)。
Store的職責(zé)
- 維持應(yīng)用的state;
- 提供
getState()
方法獲取state; - dispatch(action) 更新state;
- subscribe(listener)注冊(cè)監(jiān)聽器;
- subscribe(listener)返回的函數(shù)注銷監(jiān)聽器;
這里需要再?gòu)?qiáng)調(diào)一下:Redux 和 React 之間沒有關(guān)系。Redux 支持 React、Angular、Ember、jQuery 甚至純 JavaScript。
為了讓用戶監(jiān)聽?wèi)?yīng)用數(shù)據(jù)改變,Store 允許使用store.subscribe方法設(shè)置監(jiān)聽函數(shù),一旦 State 發(fā)生變化,就自動(dòng)執(zhí)行這個(gè)函數(shù)。
在src/index.js入口文件中:
import store from './redux/store'
...
store.subscribe(()=>{
root.render(<App/>)
})
react-redux
本庫(kù)并不是 Redux 內(nèi)置,需要單獨(dú)安裝,是Redux官方提供的React綁定庫(kù)。
安裝文章來源:http://www.zghlxwxcb.cn/news/detail-791806.html
npm i react-redux
redux將組件分為了UI組件和容器組件兩類:
- UI組件:不能使用任何redux的api,只負(fù)責(zé)頁(yè)面的呈現(xiàn)、交互等。
- 容器組件:負(fù)責(zé)和redux通信,將結(jié)果(采用父子通信)傳給UI組件。
Provider
<Provider store>
使組件層級(jí)中的 connect()
方法都能夠獲得 Redux store。
在src/index.jsx文件下:
...
root.render(
<Provider store={store}
<App/>
</Provider>)
目的:讓 <App>
所有的后代容器組件都能接收到store。
Connect
用于連接React組件與Redux store。
connect(mapStateToProps,mapDispatchToProps)
-
mapStateToProps(state, [ownProps]): stateProps] (Function)
- 映射狀態(tài)。
- 該回調(diào)函數(shù)必須返回一個(gè)純對(duì)象,這個(gè)對(duì)象會(huì)與組件的 props 合并。
- 如果定義該參數(shù),組件會(huì)監(jiān)聽redux store的變化,只要store發(fā)生改變,mapStateToProps就會(huì)被調(diào)用。
-
mapDispatchToProps(dispatch, [ownProps])
-
映射操作狀態(tài)的方法。
-
mapDispatchToProps可以是一個(gè)Function,也可以是Object,作用是綁定action創(chuàng)建函數(shù)到props上。
-
如果傳遞的是一個(gè)對(duì)象,那么每個(gè)定義在該對(duì)象的函數(shù)都將被當(dāng)作Redux action creator,而且這個(gè)對(duì)象會(huì)與 Reduxstore綁定在一起,其中所定義的方法名將作為屬性名,合并到組件的 props 中;
-
如果傳遞的是一個(gè)函數(shù),該函數(shù)將接收一個(gè) dispatch 函數(shù),然后由你來決定如何返回一個(gè)對(duì)象,這個(gè)對(duì)象通過 dispatch 函數(shù)與action creator 以某種方式綁定在一起。
-
例:
頭部的引入:
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {
increment,
decrement,
} from '../../redux/actions/count'
mapDispatchToProps返回值為函數(shù)時(shí):
connect(
state=>(count:state.count),
dispatch=>({
increment:number=> dispatch(increment(number)),
decrement:number=> dispatch(decrement(number))
})
)
mapDispatchToProps返回值為對(duì)象時(shí):
采用了對(duì)象的簡(jiǎn)寫形式
connect(
state=>(count:state.count),
{increment,decrement}
)
react-redux的開發(fā)者工具
redux-devtools-extensionredux這個(gè)插件是官方提供的可以查看狀態(tài)的ui插件,讓我們?cè)诤芏嘟M件的情況下,也能知道每個(gè)組件的數(shù)據(jù)情況,非常貼心。
安裝
npm i redux-devtools-extension
配置文章來源地址http://www.zghlxwxcb.cn/news/detail-791806.html
import {composeWithDevTools} from 'redux-devtools-extension'
...
const store = createStore(reducer,composeWithDevTools(applyMiddleware(thunk)))
到了這里,關(guān)于【React】React——redux的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!