redux的index.js暴露如下幾個接口html
export {
createStore,
combineReducers,
bindActionCreators,
applyMiddleware,
compose,
__DO_NOT_USE__ActionTypes
}
先看createStore方法,下面是使用方法git
const store = createStore(rootReducer)
下面爲createStore的實現過程及返回值github
//初始化時設置一個默認的action dispatch({ type: ActionTypes.INIT }) return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable }
createStore返回了一些方法給store
dispatch在執行時先進行驗證保證dispatch的參數action是有效的,而後執行下述代碼redux
try { isDispatching = true //改變state currentState = currentReducer(currentState, action) } finally { isDispatching = false } //觸發監聽 const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action
經過currentState = currentReducer(currentState, action)來改變state,其中currentReducer是初始化store時傳入的參數rootReducer。segmentfault
看看currentReducer是什麼api
export default combineReducers({ todos, visibilityFilter })
從使用方法上看是combineReducers接口的返回值閉包
return function combination(state = {}, action) { let hasChanged = false const nextState = {} for (let i = 0; i < finalReducerKeys.length; i++) { const key = finalReducerKeys[i] const reducer = finalReducers[key] const previousStateForKey = state[key] const nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { const errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } //將改變後的state存放到全局變量 nextState[key] = nextStateForKey //判斷state是否改變 只要有一個key變了就認爲state改變了 hasChanged = hasChanged || nextStateForKey !== previousStateForKey } //根據是否改變選擇返回舊state仍是新的state return hasChanged ? nextState : state }
返回的是combineReducers閉包函數,在返回以前先對reducer裏面的方法進行驗證保證方法好用app
currentReducer(currentState, action)實際上就是combination(currentState, action),與舊的state進行比較來肯定是否更新異步
componentdidmount(){ const {changeCurrentMonday,changeCurrentMonth} = this.props; changeCurrentMonday(data); }
... const mapDispatchToProps = (dispatch) => { return bindActionCreators({ changeCurrentMonday: actions.changeCurrentMonday, changeCurrentMonth: actions.changeCurrentMonth, changeCurrentSchedule: actions.changeCurrentSchedule }, dispatch); } export default connect(null, mapDispatchToProps)(Schedule);
const store = createStore(reducer,applyMiddleware(mid1,mid2));
再回頭看看createStore方法,方法一共三個形參:reducer, preloadedState, enhanceride
// 第二個參數是function且第三個參數不存在時,將二三參數互換 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } //確保第三個參數enhancer是一個函數 若是是 用enhancer(createStore)(reducer, preloadedState)做爲返回值 if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) }
因此上面的createStore執行的其實是applyMiddleware(mid1,mid2)(createStore)(reducer, preloadedState),applyMiddleware返回一個閉包函數,最終執行的代碼爲
function(reducer, preloadedState) { const store = createStore(reducer, preloadedState) let dispatch = () => { throw new Error( `Dispatching while constructing your middleware is not allowed. ` + `Other middleware would not be applied to this dispatch.` ) } const middlewareAPI = { getState: store.getState, dispatch: (reducer, preloadedState) => dispatch(reducer, preloadedState) } const chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } }
applyMiddleware是經過加強dispatch實現的,最終將加強後的dispatch返回,其中middlewareAPI 中的dispatch使用()=>dispatch()是爲了保證每個中間件的dispatch引用獨立。
假若有兩個中間件func1,func2(中間件格式({state,dispatch})=>(next)=>(action)=>{return next(aciton);})
chain的格式爲
[//func1
(next)=>(action)=>{next(action);},
//func2
(next)=>(action)=>{next(action);}]
如今看一下compose實現
export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (...args) => a(b(...args))) }
function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
thunk異步就是經過不調用next(action)跳出循環實現的。
經過dispatch一個異步function(例func1)攔截更新state,在func1中再dispatch一個action實現異步更新state數據。
參考文章:
http://www.javashuo.com/article/p-ngqqhicf-y.html