Redux 簡要的說就是一個事件分發器和全局
state
控制檯。react
Redux 有一個全局的state
,經過將根組件包進Provider
,將store
分發給全部的子組件,而子組件經過connect
方法,獲取dispatch
事件分發函數,以及須要的props
(若是有須要也能夠經過connect
傳入想分發給子組件的action
)npm
// Reducer/ConstValue.js export const ADD_NEW = 'add_new'; export const INCREASE = 'increase'; export const DECREASE = 'decrease'; export const DELETE = 'delete'; export INITIAL_STATE = { objList: [ { number: 0 } ] }; // Reducer/ActionCreator.js import { ADD_NEW, DELETE INCREASE, DECREASE } from './ConstValue'; export function addNew(obj) { return { type: ADD_NEW, obj } } export function delete(index) { return { type: DELETE, index } } export function increase(number, index) { return { type: INCREASE, number, index } } export function decrease(number, index) { return { type: DECREASE, number, index } }
Reducer 會註冊給 store,用於處理 action 事件redux
// Reducer/Reducers.js import { ADD_NEW, DELETE INCREASE, DECREASE, INITIAL_STATE } from './ConstValue'; let objList = INITIAL_STATE.objList; export function objList(state=objList, action) { switch (action.type) { case ADD_NEW: return [...state, action.obj]; case DELETE: return [...state.slice(0, action.index), ...state.slice(action.index + 1) ]; case INCREASE: case DECREASE: return [...state.slice(0, action.index), Object.assign({}, state[action.index], {number: number(state[action.index].number, action)}), ...state.slice(action.index + 1) ]; default: return state; } } export function number(state=objList[0].number, action) { switch (action.type) { case INCREASE: return state + action.number; case DECREASE: return state - action.number; default: return state; } }
IMPORTANT數組
Reducer 傳入(state, action), 經過判斷action
的type
, 進行事件分發處理。當事件不少的時候能夠把 Reducer 拆分, 最後經過combineReducers
進行組合。架構
每一個 Reducer 都要有明確的返回值,當siwtch
到default
的時候則返回傳入的state
自己。在處理state
的時候,不要在原有參數上修改, 而應該返回一個新的參數, 例如app
return Object.assign({}, state[0], {number: action.number}); // 經過Object.assign獲取一份state[0]的拷貝, 並修改state[0]中的number數據 return [...state, action.obj]; // 經過[...XXX]獲得一個新的數組, 並在最後加入action.obj
// Reducer/index.js import { combineReducers } from 'redux'; import * as appReducers from './Reducers'; export const AppReducer = combineReducers(appReducers);
上述代碼中, 經過import * as appReducers
導出所有的 Reducer, 以後利用combineReducers
黑魔法快速的組合 Reducer ide
黑魔法發動條件函數
每一個 Reducer 的名稱, 必須與它獲取的 state 參數名稱同樣, 例如:spa
export function objList(state=objList, action){} export function number(state=objList[0].number, action){}
若是你任性的不想那麼寫, 那麼就要:code
// Reducer/Reducers.js export function reducerA(state=objList, action){} export function reducerB(state=objList[0].number, action){} // Reducer/index.js import { combineReducers } from 'redux'; import { reducerA reducerB, } from './Reducers'; export function AppReducer(state, action) { return { objList: reducerA(state.objList, action), number: reducerB(state.objList[0].number, action) } }
// 安裝React綁定庫 sudo npm install --save react-redux
在根組件上, 經過Provider
注入store
只有一個Store
// App/index.js import { Provider } from 'react-redux'; import { createStore } from 'redux'; import { AppReducer } from '../Reducer/index'; import RootComponent from './RootComponent'; let appStore = createStore(AppReducer); render( <Provider store={appStore}> <RootComponent /> </Provider>, document.getElementById('index_body') ); // App/RootComponent.js import ContentComponent from './ContentComponent'; class RootComponent extends Component { render() { return ( <div> <ContentComponent /> <div> ) } } export default ContentComponent;
注入store
後, 根組件全部的組件均可以獲取到dispatch
函數, 以便進行action
的分發處理
// App/ContentComponent.js import { increase, decrease } from '../Reducer/ActionCreator'; class ContentComponent extends Component { render() { const {obj, increaseNumber, decreaseNumber} return ( <div> <span onClick={() => { increaseNumber(1); }}>加一</span> <span>{obj.number}</span> <span onClick={() => { decreaseNumber(1); }}>減一</span> </div> ) } } // 定義props篩選函數, 以state做爲傳入參數, 選出須要注入該組件做爲props的state. 不是必須, 不寫則state做爲props所有注入 const mapStateToProps = (state) => { return { obj: state.objList[0] // objList: state.objList // 原本想寫list增刪邏輯的可是太懶了暫時擱淺.. } } // 定義action篩選函數, 以dispatch做爲傳入參數, 選出須要注入該組件須要使用的action. 不是必須 const mapDispatchToProps = (dispatch) => { return { increaseNumber: (number) => { dispatch(increase(number)); }, decreaseNumber: (number) => { dispatch(decrease(number)); } } } import { connect } from 'react-redux'; export default connect(mapStateToProps, mapDispatchToProps)(ContentComponent); // 不使用篩選函數的時候: // export default connect(mapStateToProps)(ContentComponent); // export default connect()(ContentComponent);
在經過connect
進行注入的時候, dispatch
已經做爲組件的 props 而存在了。因此當須要傳入的事件不少, 感受寫mapDispatchToProps
很繁瑣的時候, 還有另一種寫法:
// App/ContentComponent.js import { increase, decrease } from '../Reducer/ActionCreator'; class ContentComponent extends Component { render() { const {obj, dispatch} return ( <div> <span onClick={() => { dispatch(increaseNumber(1)); }}>加一</span> <span>{obj.number}</span> <span onClick={() => { dispatch(decreaseNumber(1)); }}>減一</span> </div> ) } } import { connect } from 'react-redux'; export default connect(mapStateToProps)(ContentComponent);
經過 Redux, 咱們能夠少些不少繁瑣的事件傳輸。在 Redux 以前, 頂層組件處理 state 的改變, 而觸發的事件則有可能須要層層傳遞給底層的子組件, 子組件觸發以後再次層層回調傳到頂層。
但 Redux 的 state 是全局的, 沒必要關心哪一個組件觸發setState()
函數, 只須要設定好action
和處理 action 的reducer
, 由store
進行分發處理。
那樣的話, 咱們能夠在底層觸發 state 的改變而沒必要擔憂向上調用 --- 觸發的 action 改變將被 store 監聽, dispatch 給 reducer, reducer經過判斷action.type
, 作出適當的反應處理 state
action 不少很繁瑣
一開始的架構很重要,不然後期改動不易
淡化了傳統React的組件傳輸事件與props的思想, 可能一開始不易理解