redux
是什么、有什么做用,解决什么问题,若是你还不知道,请先去这里: redux中文文档git
下面的文章适合对redux有必定理解和使用经验的人github
项目github地址:github.com/wangweiange…redux
若是你以为对你有帮助的话记得给我一个star呢数组
使用包含自定义功能的 middleware 来扩展 Redux 是一种推荐的方式。promise
Middleware 可让你bash
同时, middleware 还拥有“可组合”这一关键特性。多个 middleware 能够被组合到一块儿使用,造成 middleware 链。app
其中标红色的部分是咱们很经常使用到的,例如redux-thunk
、redux-promise
插件。异步
若要很好的理解applyMiddleware
咱们归入redux-thunk
源码来分析:函数
先看看 applyMiddleware的源码:
学习
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}复制代码
很是的简洁,总体含义就是:applyMiddleware 接收多个参数,并返回一个以createStore为参数的function,此function通过一系列的处理以后返回了 createStore里面的全部方法和重写的dispatch。
这里仍是不能很好理解的话咱们来看看redux-thunk
的源码:
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;复制代码
也是很是的简洁接收一个extraArgument参数,返回一个{ dispatch, getState }为参数的function,即最终返回的是这个函数:
从源码中能够看出 thunk 最终的值为 这个function
({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};复制代码
让咱们来简化一下它用通俗的方式改写以下,
//用通俗的代码重写
let AAA = function (opt) {
var dispatch = opt.dispatch,
getState = opt.getState;
return function (next) {
return function (action) {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
};
};复制代码
能够很清晰的看出,传入了dispatch和getState,返回了一个函数,并判断函数的action参数是否为function作不一样的处理,其中标识为红色的为实现异步的核心。
也许仍是不能理解因此然,下面让咱们来理清它。
import thunk from 'redux-thunk'
import { createStore,applyMiddleware } from './redux'
const store = createStore(
reducers,
applyMiddleware(thunk)
)复制代码
import thunk from 'redux-thunk'
import { createStore,applyMiddleware } from './redux'
const ADD_TODO = 'ADD_TODO'
function reducers(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([ action.text ])
default:
return state
}
}
// 建立 Redux 的 store 对象
const store = createStore(
reducers,
applyMiddleware(thunk)
)
console.log(store.getState())复制代码
下面我经过在代码中注释的方式来讲明运行流程:
//此时 ...middlewares = [ AAA ] AAA在上面有说明
export default function applyMiddleware(...middlewares) {
//返回一个函数 惟一的参数为 createStore,也就是redux中的createStore函数
return (createStore) => (reducer, preloadedState, enhancer) => {
//这里相执行了createStore方法 传了3个参数,
//这三个参数从createStore.js 中的 return enhancer(createStore)(reducer, preloadedState) 得来,能够看出传来的参数只有2个
//所以也就不会再执行createStore.js中的 enhancer函数
const store = createStore(reducer, preloadedState, enhancer)
//这里获得了store,拿取createStore.js 中的dispatch函数 存储在dispatch临时变量中
let dispatch = store.dispatch
//由于 ...middlewares 是一个数组,临时存储
let chain = []
//包装 getState 和 dispatch 两个方法
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
/*
循环调用
体如今案例中时 middlewares 的值为 [AAA] 所以运行一次
返回的chain为 [ AAA(middlewareAPI) ], 能够看出middlewareAPI值正是AAA函数须要的两个参数
体如今案例中此时 chain 值为:
[
function (next) {
return function (action) {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
},
]
*/
chain = middlewares.map(middleware => middleware(middlewareAPI))
/*
这段代码运行完以后会获得新的dispatch
体如今案例中下面这段代码返回值dispatch为:
function (action) {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return store.dispatch(action);
};
这里的面的 next 值为 store.dispatch
*/
dispatch = compose(...chain)(store.dispatch)
//最终返回新的createStore方法,重写了dispatch,其余的都没有变
return {
...store,
dispatch
}
}
}复制代码
根据以上的分析咱们来给一个异步的actions案例,并dispatch调用:
function actions(){
return (dispatch)=>{
dispatch({
type: ADD_TODO,
text: 'Read the docs'
})
}
}
//使用redux-think处理以后的dispatch触发actions
store.dispatch(actions())复制代码
根据以上的分析咱们知道最终处理以后返回的dispatch
值为:
function (action) {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return store.dispatch(action);
};复制代码
当调用actions()以后咱们能够明显的看出 typeof action === 'function' 为真
所以走是return action(dispatch, getState, extraArgument);
,再去触发reducers函数
最终经过 currentState = currentReducer(currentState, action)
从而改变惟一的store状态数据
通过以上的分析就能很好的理解alpplyMiddleware
这个方法和redux-thunk
的主要做用了。
接下来咱们进入到redux的最后一个方法 bindActionCreators
redux v3.7.2源码解读与学习之 bindActionCreators
关注个人博客:zane的我的博客