本文記錄的是本身對redux的學習和理解,但願能夠簡潔易懂,入門redux
,一步步的走進redux
!react
Redux
是JavaScript
應用的狀態容器,提供可預測化的狀態管理,讓你構建一致化的應用,運行於不一樣的環境(客戶端、服務器、原生應用),而且易於測試。不只於此,它還提供超爽的開發體驗。redux
【store
】保存應用狀態全局單一緩存
【state
】全部state
以key-value的形式存儲在store
中服務器
【action
】描述發生什麼的對象,觸發action
是惟一改變state
的方式,action
本質上是一個普通js對象,必必須一個type
字段,值爲字符串常量網絡
【action creator
】建立action
app
【reducer
】描述action
如何改變state
ide
建立一個Redux store
來以存放應用中全部的state
。函數
隨着應用複雜度上升,數據源逐漸變混亂,致使組件內部數據調用十分複雜,會產生數據冗餘或者混用等狀況,須要對reducer
函數進行拆分,拆分後的每一模塊獨立負責管理state
的一部分。combineReducers
函數的做用是,返回一個最終的rootReducer
函數,rootReducer
作的事情是獲得一個由多個不一樣reducer
函數做爲value(key能夠自定義)的對象。學習
const module1Reducer = combineReducers( module1_key1: module1_reducer1 ); const rootReducer = combineReducers( key1: reducer1, module1: module1Reducer ); const store = createStore(rootReducer); // store中保存的state結構以下 { key1: reducer1(state.key1, action), module1: { module1_key1: (state.module1.module1_key1, action) } }
總結一下,state
對象的結構由傳入的多個reducer
的key決定,能夠根據模塊拆分的細粒度,考慮是否須要嵌套使用combineReducers
,整個應用的數據大體分來兩類:普通data和ui狀態測試
+ data - 服務器響應的數據 - 緩存數據 - 本地還沒有持久化到服務器的數據 - 用戶輸入 - ... + ui狀態 - 激活的路由 - 被選中的Tab標籤 - 是否顯示加載動畫 - 分頁器狀態 - ...
設計state
結構時,儘可能把state
範式化,不要存在嵌套不一樣類型的對象的狀況。把數據放到一個對象(列表)中,每一個數據用id
做爲主鍵。不一樣類型的對象經過id
引用數據,這樣數據發生改變的時候,只須要修改一處地方,減小數據冗餘或者混用。
首先要介紹一下什麼是middlewares
,middlewares
用於包裝store.dispatch
,擴展其功能,在發起action以後,到達reducer以前執行一些邏輯,有點相似是aop的一種實現。
applyMiddleware大體實現:
暫存redux store
提供的dispatch
把dispatch
做爲實參,傳給middleware
執行以後返回的函數A
執行函數A,返回包裝過的dispatch
,覆蓋原來的store.dispatch
function applyMiddleware(store, middlewares) { middlewares = middlewares.slice() middlewares.reverse() // 暫存dispatch let dispatch = store.dispatch // 包裝dispatch middlewares.forEach(middleware => dispatch = middleware(store)(dispatch) ) return {...store, { dispatch }) }
理解了applyMiddleware
的邏輯,自定義一個middleware
大體以下
function(store){ // pass store.dispatch to next return function(next){ // return dispatch return function(action){ // implement middleware logic } } }
參數actionCreators若是爲函數 把 action creators
轉成擁有同名keys
的對象,但使用 dispatch
把每一個action creator
包圍起來,返回新的對象
參數actionCreators若是爲對象,若actionCreators[key]爲函數,用dispatch
把每一個 actionCreators[key]包圍起來,返回新的對象
組合store enhance,applyMiddleware 和 redux-devtools就是store enhance
Redux
自己只提供應用狀態和數據流管理,除了和React
一塊兒用外,還支持其它界面庫,且沒有任何依賴。要在React
的項目中使用Redux
,比較好的方式是藉助react-redux這個庫來作鏈接.
爲整個應用提供store
數據,作的事情是把store
做爲props傳遞到每個被connet()
包裝的組件
connect(...args)(component)返回一個與Redux store
鏈接的組件類,下面簡單講解一下connect
方法的參數
state
是store
中整個應用的state
ownProps
高階函數包裝過的組件的props
該回調函數必須返回一個純對象,這個對象會與被包裝的組件的props作merge合併
mapStateToProps
能夠作一些數據的format, filter,compose操做,保證數據在組件層面的方便使用
mapDispatchToProps
參數爲Object
, 每一個定義在該對象的函數都將被看成Redux action creator
,其中所定義的方法名將做爲屬性名,合併到被包裝的組件的props中,實現的效果:執行component.prop.checkout()其實是dispatch
了一個action
,這樣作的好處是component與redux的解耦,component根本不知道redux的存在。
// action creator返回對象 mapDispatchToProps = { // action creator checkout: function actionCreator(productId){ return { type: types.ADD_TO_CART, productId } } } // action creator返回函數,thunk mapDispatchToProps = { // action creator checkout: function actionCreator(productId){ action creator 返回一個thunk, thunk的參數爲 dispatch 和 getState return (dispatch, getState) => { if (getState().products.byId[productId].inventory > 0) { dispatch(addToCartUnsafe(productId)) } } } } // 最終被綁定的組件props component.props.checkout = function () { return dispatch(actionCreator.apply(undefined, arguments)); }
mapDispatchToProps
參數爲Function
mapDispatchToProps(dispatch, [ownProps]) = function(){ return { checkout: () => { dispatch(actionCreator()) } } } // 最終被綁定的組件.props component.props.checkout = function () { return dispatch(actionCreator.apply(undefined, arguments)); } // 使用bindActionCreators mapDispatchToProps(dispatch, [ownProps]) = function(){ return bindActionCreators(actionCreator, dispatch) } // 最終被綁定的組件props component.props.actionCreator = function () { return dispatch(actionCreator.apply(undefined, arguments)); } // 使用 bindActionCreators mapDispatchToProps(dispatch, [ownProps]) = function(){ return bindActionCreators({ ‘checkout’: actionCreator }, dispatch) } // 最終被綁定的組件props component.props.checkout = function () { return dispatch(actionCreator.apply(undefined, arguments)); }
dispatch(actionCreator) => Reducer => (state, action) => state
用戶操做或者網絡請求 store.dispatch(action)
redux store
調用傳入的rootReducer
redux
執行所有的reducer,把每一個reducer
執行獲得的結果輸出合成一個新的對象
store
存儲rootReducer
返回的值,更新currentState