對(duì)于剛學(xué)習(xí)rn的人來(lái)說(shuō)阱扬,看到redux肯定會(huì)一臉懵幽污。redux是干啥的呢,網(wǎng)上也有很多介紹咕痛,我就不做過(guò)多介紹了痢甘,個(gè)人把他理解成一個(gè) 小型數(shù)據(jù)庫(kù),用來(lái)處理數(shù)據(jù)的。更多詳細(xì)內(nèi)容看官方的吧茉贡,我只做一個(gè)個(gè)人對(duì)其理解的簡(jiǎn)單介紹塞栅。
首先我們知道rn中通過(guò)state、props這兩種方式控制組件腔丧,redux就是通過(guò)改變state來(lái)控制組件的變化放椰。怎么改變的呢,大體講一下流程吧:
1愉粤、首先我們點(diǎn)擊按鈕或者網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求回來(lái)的時(shí)候需要發(fā)消息到action內(nèi)
2砾医、action將消息預(yù)處理,即區(qū)分type衣厘,然后返回給store如蚜。
3、store將分類好的消息分配到reducer中處理state影暴。
4错邦、reducer接收到消息、根據(jù)type做對(duì)應(yīng)的處理坤检,生成新的state返回給store
5兴猩、store控制頁(yè)面渲染
不多說(shuō)了,還是邊上代碼邊做講解比較好早歇,先用著倾芝,然后慢慢再理解讨勤。當(dāng)我們使用redux的時(shí)候就需要在項(xiàng)目里添加redux依賴。
npm install --save redux
npm install --save react-redux
npm install --save redux-thunk
redux核心就三部分:Action晨另、Reducer潭千、Store。
- Action
想要更新state中的數(shù)據(jù)借尿,就要發(fā)起一個(gè)動(dòng)作刨晴,這就用到action了。Action內(nèi)部必須使用一個(gè)字符串類型的type
來(lái)表示要執(zhí)行的動(dòng)作路翻。一般type
都定義成字符串常量狈癞。Action只能描述有事情發(fā)生了,不能搞其他的茂契。
import * as types from '../constants/LoginTypes'
let user = {
name: '小明',
age: 25
}
// 這里發(fā)起Action
export function login() {
return dispatch => {
dispatch(isLogining());
let result = fetch('https://www.baidu.com')
.then((res) => {
dispatch(loginSuccess(true, user))
}).catch((err) => {
dispatch(loginError(false))
})
}
}
// 這個(gè)Action標(biāo)識(shí)正在登錄
function isLogining () {
return {
type: types.LOGIN_IN_DOING
}
}
// 這個(gè)Action標(biāo)識(shí)登錄成功
function loginSuccess(isSuccess, user) {
console.log('loginSuccess')
return {
type: types.LOGIN_IN_DONE,
user: user.name
}
}
// 這個(gè)Action標(biāo)識(shí)登錄失敗
function loginError(isSuccess){
console.log('error')
return {
type: types.LOGIN_IN_ERROR
}
}
- Reducer
reducer是干啥用的呢蝶桶,個(gè)人理解其實(shí)就是MVC中的Model模型。舉個(gè)例子吧掉冶,我們頁(yè)面要展示用戶名真竖、性別、年齡厌小、住址等信息恢共,這時(shí)我們服務(wù)端接口里給返回的格式如下,這時(shí)我們需要對(duì)這些字段做處理璧亚、存數(shù)據(jù)讨韭、發(fā)送給store做頁(yè)面展示用。reducer就干這個(gè)用的涨岁。
{
status:0,
userName:"小李",
age:25,
sex:"man"
address:"北京"
}
還是直接上代碼吧
import * as types from '../constants/LoginTypes'
const initialState = {
status: '點(diǎn)擊登錄',
isSuccess: false,
user: null
}
export default function longinIn(state = initialState, action) {
switch (action.type) {
case types.LOGIN_IN_DOING:
return {
...state,
status: '正在登錄',
isSuccess: false,
user: null
}
break;
case types.LOGIN_IN_DONE:
return {
...state,
status: '登錄成功',
isSuccess: true,
user: action.user
}
break;
case types.LOGIN_IN_ERROR:
return {
...state,
status: '登錄失敗',
isSuccess: false,
user: null
}
default:
return state;
}
}
// 當(dāng)然我們會(huì)有多個(gè)reducer拐袜,那么我們需要把不同的reducer關(guān)聯(lián)到一起提供給store
import { combineReducers } from 'redux'
import loginIn from './loginReducer'
import counterIn from './CounterReducer'
module.exports = combineReducers({
loginIn:loginIn,
counterIn:counterIn
})
有碼就好理解我說(shuō)的model了吧,initialState是初始化梢薪。下邊是根據(jù)action的type
類型做相應(yīng)的處理蹬铺。
- Store
store是把a(bǔ)ction、reducer聯(lián)系到一起的對(duì)象秉撇。它負(fù)責(zé)一下職責(zé)
- 維持應(yīng)用的 state甜攀;
- 提供 getState() 方法獲取 state;
- 提供 dispatch(action) 方法更新 state琐馆;
- 通過(guò) subscribe(listener) 注冊(cè)監(jiān)聽器;
- 通過(guò) subscribe(listener) 返回的函數(shù)注銷監(jiān)聽器规阀。
'use strict';
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import rootReducer from '../reducers/index';
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState)
return store;
}
Redux 應(yīng)用只有一個(gè)單一的store。當(dāng)需要拆分?jǐn)?shù)據(jù)處理邏輯時(shí)瘦麸,你應(yīng)該使用 reducer 組合 而不是創(chuàng)建多個(gè) store谁撼。
- 上邊三步還不行,還需要下邊最重要的一步滋饲,state關(guān)聯(lián)
const mapStateToProps = (state) => {
return {
user: state.loginIn.user,
}
}
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators({
...loginAction
}, dispatch)
}
}
module.exports = connect(mapStateToProps, mapDispatchToProps, undefined, { withRef: true })(App)