1.安裝
redux是獨(dú)立的數(shù)據(jù)狀態(tài)管理插件,要想和react搭配使用梗劫,還需要添加react-redux用來(lái)將二者鏈接起來(lái)享甸,發(fā)揮其強(qiáng)大作用。
npm install redux react-redux --save
2.創(chuàng)建唯一數(shù)據(jù)中心store
利用redux的createStore創(chuàng)建唯一數(shù)據(jù)中心store在跳,createStore接受reducer為第一個(gè)參數(shù)枪萄,中間件作為第二個(gè)參數(shù)(此處引用的redux-thunk插件用于擴(kuò)展reducer不僅可以接受action對(duì)象作為參數(shù),同時(shí)還能接受一個(gè)函數(shù)作為參數(shù)猫妙,由此實(shí)現(xiàn)在action中實(shí)現(xiàn)異步請(qǐng)求)瓷翻。
subscribe 這個(gè)函數(shù)是用來(lái)去訂閱 store 的變化,比如你每次對(duì) store 進(jìn)行 dispatch(action) 都會(huì)觸發(fā) subscribe 注冊(cè)的函數(shù)調(diào)用,這個(gè)在實(shí)際情況不是必須要的齐帚,看自己的應(yīng)用場(chǎng)景妒牙,比如你想監(jiān)控 store 的全局變化時(shí) 可以用 subscript 訂閱一下,然后作一些反應(yīng)对妄。
import { createStore, applyMiddleware } from 'redux';
import reducers from '../reducers/index'
import thunk from 'redux-thunk'
let store = createStore(reducers, applyMiddleware(thunk));
// 可以手動(dòng)訂閱更新湘今,也可以事件綁定到視圖層。
store.subscribe(() =>
console.log(store.getState())
);
export default store;
3.修改store內(nèi)數(shù)據(jù)的唯一動(dòng)作提交action
要想修改store內(nèi)的數(shù)據(jù)唯一方法就是提交action剪菱,action是一個(gè)帶有tyoe屬性的對(duì)象摩瞎,其他屬性可以任意填寫。編寫action需要注意幾點(diǎn):
- 單獨(dú)存儲(chǔ)action的type孝常,避免不必要的無(wú)提示的錯(cuò)誤編寫旗们;
- 通過(guò)函數(shù)創(chuàng)建action,前面我們說(shuō)過(guò)构灸,引入了redux-thunk插件上渴,他允許action返回一個(gè)函數(shù)作為dispatch的對(duì)象,例如actionCreator.js中的getData函數(shù)喜颁。
//actionTypes.js
const Types = {
SET_DATA: 'SET_DATA',
SET_NORMAL: 'SET_NORMAL',
SET_LOADING: 'SET_LOADING'
};
export default Types;
// actionCreator.js
import Types from './actionTypes';
const actionCreator = {
setLoading: () => {
return {
type: Types.SET_LOADING,
payload : {
loading: true
}
}
},
getData: () => {
return (dispatch, getState) => {
let action = {
type: Types.SET_DATA,
payload: {
loading: false
}
};
console.log(getState());
setTimeout(() => {
dispatch(action);
}, 3000);
}
},
normal: () => {
return {
type: Types.SET_NORMAL,
payload: {
count: 4
}
}
}
}
export default actionCreator;
4.神奇的reducer
reducer是唯一可以更改store中數(shù)據(jù)的方法稠氮,而且reducer應(yīng)該是一個(gè)沒(méi)有任何副作用的純函數(shù),即固定輸入半开,固定輸出(每次輸入同樣的數(shù)據(jù)都應(yīng)該得到唯一的輸出)隔披,這里的副作用值得是setTimeout、異步請(qǐng)求等操作稿茉。以下代碼展示了將reducer如何進(jìn)行拆分锹锰,利用redux的combineReducers函數(shù),將多個(gè)reducer合并為一個(gè)reducer返回漓库。導(dǎo)出的大reducer作為createStore的第一參數(shù)恃慧。
// index.js
import { combineReducers } from 'redux'
import home from './home'
import detail from './detail'
export default combineReducers({
home,
detail
});
// reducer 是純函數(shù),輸入固定渺蒿,輸出固定
// 不能含有任何副作用代碼
import Types from '../actions/actionTypes'
let defaultState = {
flag: 1,
loading: false
};
const home = (state = defaultState, action) => {
switch (action.type) {
case Types.SET_DATA:
return Object.assign({}, state, {
flag: state.flag + 1,
loading: action.payload.loading
})
case Types.SET_LOADING:
return Object.assign({}, state, {
loading: action.payload.loading
})
case Types.SET_NORMAL:
return Object.assign({}, state, {
flag: state.flag + action.payload.count
})
default:
return state;
}
}
export default home;
//detail.js
let defaultState = {};
const detail = (state = defaultState, action) => {
switch(action.type){
default:
return state;
}
}
export default detail;
5.react和redux的強(qiáng)力膠水react-redux
react作為視圖層框架痢士,用于管理用戶界面,而redux作為數(shù)據(jù)層框架茂装,用于幾種管理數(shù)據(jù)怠蹂,如何將二者聯(lián)系起來(lái),統(tǒng)一管理數(shù)據(jù)少态,數(shù)據(jù)變動(dòng)觸發(fā)視圖更新呢城侧?答案就是強(qiáng)力膠水react-redux,react-redux利用connect函數(shù)將react視圖組件和store中的數(shù)據(jù)連接起來(lái)彼妻,具體代碼:
import React, { Component } from 'react';
import { Button } from 'antd';
import { connect } from 'react-redux';
import actionCreator from '../actions/actionCreator';
class TestRedux extends Component {
handleClick () {
this.props.setLoading();
this.props.getData();
}
render () {
return (
<div>
<div>{this.props.flag}</div>
<Button
onClick={this.handleClick.bind(this)}
type="primary"
>增加</Button>
<Button
onClick={this.props.getCount}
type="primary"
>增加4</Button>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
console.log(ownProps);
return {
flag: state.home.flag
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
console.log(ownProps);
return {
getData () {
const action = actionCreator.getData();
dispatch(action);
},
getCount () {
const action = actionCreator.normal();
dispatch(action);
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(TestRedux);
react-redux的 connect函數(shù)接受兩個(gè)參數(shù)mapStateToProps和mapDispatchToProps,正如兩個(gè)函數(shù)的名字一樣嫌佑,兩個(gè)函數(shù)返回一個(gè)映射豆茫,一個(gè)是state => props的映射,一個(gè)是dispatch => props 的映射屋摇,將store中的數(shù)據(jù)映射到對(duì)應(yīng)組件的props屬性上揩魂,這樣我們便可以再組件中使用這些屬性。
注意
利用redux-thunk我們返回了getData這個(gè)異步函數(shù)action炮温,細(xì)心的朋友可能已經(jīng)發(fā)現(xiàn)火脉,我再組件中映射dispatch時(shí),利用actionCreator創(chuàng)建了getData的action柒啤,然后立即dispatch了這個(gè)action倦挂,而且在dispatch的這個(gè)函數(shù)中進(jìn)行了異步操作,當(dāng)操作成功后再次調(diào)用dispath白修,整個(gè)數(shù)據(jù)更新操作中dispath了兩次妒峦,我的理解是
1、立即發(fā)出的dispatch用于告知redux兵睛,我要更新數(shù)據(jù),但是我現(xiàn)在不更新窥浪,你等我下一次通知祖很。
2、異步請(qǐng)求成功后發(fā)出的dispatch就是這個(gè)下一次通知漾脂,然后redux相應(yīng)這個(gè)更新假颇,修改store中的數(shù)據(jù)。
結(jié)語(yǔ)
react和redux分管視圖和數(shù)據(jù)骨稿,實(shí)現(xiàn)了數(shù)據(jù)視圖的真正分離笨鸡,這是在大型應(yīng)用中很好地,也是易于維護(hù)的坦冠,但是任何事情都有利有弊形耗,當(dāng)應(yīng)用逐漸變大,action和reducer的量也會(huì)相應(yīng)變得更加繁瑣辙浑,雖然數(shù)據(jù)變化和流轉(zhuǎn)是明確的但是對(duì)于多數(shù)項(xiàng)目來(lái)說(shuō)激涤,還達(dá)不到足夠大,敏捷判呕、高效有時(shí)才是王道倦踢,這就是我理解的近年來(lái)vue盛行的原因。vue憑借其易學(xué)侠草、易用性迅速崛起辱挥。為了解決redux的繁瑣,mobx應(yīng)運(yùn)而生边涕,mobx采用類似vue的響應(yīng)機(jī)制晤碘,細(xì)粒度的觀測(cè)讓數(shù)據(jù)變化不再這么繁瑣褂微,下節(jié),我們會(huì)剖析mobx的基礎(chǔ)使用哼蛆,一起學(xué)起來(lái)吧!