博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redux v3.7.2源码解读与学习之 applyMiddleware
阅读量:5750 次
发布时间:2019-06-18

本文共 5388 字,大约阅读时间需要 17 分钟。

redux是什么、有什么作用,解决什么问题,如果你还不知道,请先去这里:

下面的文章适合对redux有一定理解和使用经验的人

项目github地址:

如果你觉得对你有帮助的话记得给我一个star呢

applyMiddleware有什么用:

使用包含自定义功能的 middleware 来扩展 Redux 是一种推荐的方式。

Middleware 可以让你

包装 store 的 dispatch 方法
来达到你想要的目的。

同时, middleware 还拥有“可组合”这一关键特性。多个 middleware 可以被组合到一起使用,形成 middleware 链。

其中标红色的部分是我们很常用到的,例如redux-thunkredux-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);  };复制代码

让我们来简化一下它用通俗的方式改写如下,

我们把它命名为AAA
,以方便与下面的理解:

//用通俗的代码重写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做不同的处理,其中标识为红色的为实现异步的核心。

也许还是不能理解所以然,下面让我们来理清它。

来看看createStore,applyMiddleware 加上 redux-thunk 之后的调用方式:

import thunk from 'redux-thunk'import { createStore,applyMiddleware } from './redux'const store = createStore(    reducers,    applyMiddleware(thunk))复制代码

我们来给一个reducers测试案例来分析源码的走向,完整代码如下:

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触发actionsstore.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

关注我的博客:

原文地址:

转载地址:http://kgkkx.baihongyu.com/

你可能感兴趣的文章
iOS单例
查看>>
webpack 1.x 配合npm scripts管理多站点
查看>>
windows下Emacs的安装与配置
查看>>
CF Watto and Mechanism (字典树+深搜)
查看>>
【转】jQuery教程
查看>>
关于markdown怎么在博客园展示出来的问题
查看>>
bootstrap中的 form表单属性role="form"有什么作用?
查看>>
c#日期与字符串间的转换(转)
查看>>
Java基础(四)
查看>>
移动端禁止登陆
查看>>
Steve Jobs 2005年于 Stanford University 毕业典礼上的演讲
查看>>
java中枚举类的实际应用
查看>>
课程设计__C++初步,C++对C的扩充
查看>>
Codeforces 758A Holiday Of Equality
查看>>
P25、面试题1:赋值运算符函数
查看>>
Ajax详细介绍
查看>>
前端页面优化技巧
查看>>
python3爬虫-爬取58同城上所有城市的租房信息
查看>>
c/c++工程中的各种文件【转】
查看>>
数组和集合List的相互转化
查看>>