redux並不侷限於flux與react。redux 自身保持簡潔以便適配各類場景,讓社區發展出各類 redux-* 中間件或者插件,從而造成它本身的生態系統。html
reducer 聲明瞭state的初始值,以及當前state接受action對象以後處理爲new state的邏輯。react
createStore接受reducer做爲參數,返回產生的store,store實際上是一個含有state的閉包,以及提供將action分發給reducer的dispatch方法。git
applyMiddlewares方法接受n個middlewares做爲參數返回一個用於渲染creatorStore函數的方法。github
applyMiddleware能夠向actionCreator提供store.dispatch以及getState方法,用以加強actionCreator的能力redux
store主要包含如下三個核心方法:數組
subscribe 註冊store更新以後的回調函數promise
getState 獲取store當前state的引用,切記直接修改返回的結果緩存
dispatch 將action按順序通過各middle處理後派發給reducer閉包
createStore是根據reducer中的規則建立store的方法。app
提供dispatch
subscribe
getState // getState拿到的是state的引用!不要直接修改
提供初始值initialState
//此處爲示意,不是 redux 的源碼自己 export default createStore(reducer, initialState) { //閉包私有變量 let currentState = initialState let currentReducer = reducer let listeners = [] //返回一個包含可訪問閉包變量的公有方法 return { getState() { return currentState //返回當前 state }, subscribe(listener) { let index = listeners.length listeners.push(listener) //緩存 listener return () => listeners.splice(i, 1) //返回刪除該 listener 的函數 }, dispatch(action) { //更新 currentState currentState = currentReducer(currentState, action) // 能夠看到這裏並無用到eventEmitter等 listeners.slice().forEach(listener => listener()) return action //返回 action 對象 } } }
action有如下特色:
pure object
描述reducer響應的事件類型
攜帶所須要的數據
用於描述action的dispatch的邏輯。
action的重用
數據的預處理
action的特殊處理邏輯
reducer應該是是一個無反作用函數,以當前的state以及action爲參數,返回新的state。
每次返回一個新State的好處是在shouldComponentUpdate過程當中可使用高性能的shallow equal。
pure function
接受initialState
don't modify the state!!!
//reducer 接受兩個參數,全局數據對象 state 以及 action 函數返回的 action 對象 //返回新的全局數據對象 new state export default (state, action) => { switch (action.type) { case A: return handleA(state) case B: return handleB(state) case C: return handleC(state) default: return state //若是沒有匹配上就直接返回原 state } }
將一個reducer map轉換爲一個reducer。方便對複雜的reducer進行功能拆分。
state 結構太複雜
但願根據對應的component進行維護
var reducers = { todos: (state, action) { //預期此處的 state 參數是全局 state.todos 屬性 switch (action.type) {...} //返回的 new state 更新到全局 state.todos 屬性中 }, activeFilter: (state, action) { //預期拿到 state.activeFilter 做爲此處的 state switch (action.type) {...} //new state 更新到全局 state.activeFilter 屬性中 } } //返回一個 rootReducer 函數 //在內部將 reducers.todos 函數的返回值,掛到 state.todos 中 //在內部將 reducers.activeFilter 函數的返回值,掛到 state.activeFilter 中 var rootReducer = combineReducers(reducers)
//combination 函數是 combineReducers(reducers) 的返回值,它是真正的 rootReducer //finalReducers 是 combineReducers(reducers) 的 reducers 對象去掉非函數屬性的產物 //mapValue 把 finalReducers 對象裏的函數,映射到相同 key 值的新對象中 function combination(state = defaultState, action) { var finalState = mapValues(finalReducers, (reducer, key) => { var newState = reducer(state[key], action); //這裏調用子 reducer if (typeof newState === 'undefined') { throw new Error(getErrorMessage(key, action)); } return newState; //返回新的子 state }); //...省略一些業務無關的代碼 return finalState; //返回新 state }; function mapValues(obj, fn) { return Object.keys(obj).reduce((result, key) => { result[key] = fn(obj[key], key); return result; }, {}); }
異步action
promise
個性化 action 響應
log
接受 middleWares 將 store 修飾爲使用了 middlwares 的 store,實際上是用被高階函數修飾過的dispatch替換掉了原來的dispatch。
var craeteStoreWithMiddleWare = applyMiddleWare(thunk)(createStore); //redux-thunk export default function thunkMiddleware({ dispatch, getState }) { return next => action => typeof action === 'function' ? // action 竟然是函數而不是 plain object? action(dispatch, getState) : //在中間件裏消化掉,讓該函數控制 dispatch 時機 next(action); //不然調用 next 讓其餘中間件處理其餘類型的 action }
這裏的composeMiddleware可能不是很好理解,這裏有一個簡單的例子方便你們理解。http://jsbin.com/xalunadofa/1/edit?js,console。 compose能夠理解爲倒敘一層層打包的過程,所以最後調用composedFunction的時候會順序進入各個middlewares。
function applyMiddleware(...middlewares) { return next => (...args) => { const store = next(...args); const middleware = composeMiddleware(...middlewares); // dispatch 被middlWare修飾 function dispatch(action) { const methods = { dispatch, getState: store.getState }; return compose( middleware(methods), store.dispatch )(action); } // 返回新的store dispatch被新的dispatch替代 return { ...store, dispatch }; }; }
//將 actionCreator 跟 dispatch 綁定在一塊兒 let bindActionCreator => (actionCreator, dispatch) { return (...args) => dispatch(actionCreator(...args)); } function bindActionCreators(actionCreators, dispatch) { if (typeof actionCreators === 'function') { //若是是單個 actionCreator,綁定一詞 return bindActionCreator(actionCreators, dispatch); } //返回一個改造過的「函數組合」 return mapValues(actionCreators, actionCreator => bindActionCreator(actionCreator, dispatch) ) }
connector 接受mapStateToProps, mapDispatchToProps, Component 三個參數,返回一個可以自動關聯store中state以及dispatch事件的smart component
因爲connector代碼過長,只對重要的幾個函數進行說明。
connetor函數接受的兩個參數指明從store的state中挑選哪些做爲props,以及將哪些actionCreator綁定到porps中。
訂閱store的change事件,當store更新時計算新的state,與舊state進行淺對比,若是不一樣則更新state,並render,不然不進行render。
// 根據從store中select的state以及dispatch綁定的actionCreator計算新的props computeNextState(props = this.props) { return computeNextState( this.stateProps, this.dispatchProps, props ); } // 與舊值進行shallow equal updateState(props = this.props) { const nextState = this.computeNextState(props); if (!shallowEqual(nextState, this.state.props)) { this.setState({ props: nextState }); } } // 訂閱change事件 trySubscribe() { if (shouldSubscribe && !this.unsubscribe) { this.unsubscribe = this.store.subscribe(::this.handleChange); this.handleChange(); } } tryUnsubscribe() { if (this.unsubscribe) { this.unsubscribe(); this.unsubscribe = null; } } componentDidMount() { this.trySubscribe(); } componentWillUnmount() { this.tryUnsubscribe(); } handleChange() { if (!this.unsubscribe) { return; } if (this.updateStateProps()) { this.updateState(); } }
歡迎你們發起pr完善文檔,進行討論。