新一代reduxUtils源码分析

    xiaoxiao2021-03-25  101

    ReduxUtil的实现方式

    一、connect方法:

    1.需要绑定的class

    2.mapStateToProps方法,这个方法将store中存放的状态传 到组件的props中

    function _mapDispatchToProps(dispatch) { return { dispatch: dispatch, //发送一个动作指令 sendAction: function sendAction() { dispatch(ReduxUtils.createAction.apply(this, arguments)); } }; } connect: function connect(reactClass, mapStateToProps, mapDispatchToProps) { //_connect就是redux原生的connect方法 return _connect(mapStateToProps, function (dispatch) { var _props = _mapDispatchToProps(dispatch); if (isFunction(mapDispatchToProps)) { _props = assign(_props, mapDispatchToProps(dispatch)); } return _props; })(reactClass); }

    我们可以看到,connect方法是将传入mapDispatchToProps与自己定义的dispatch合并,所以通过这种方式connect的组件默认会带有sendAction方法

    二、分析一下ReduxUtil如何新建并解析一个自己创建的action

    createAction: function createAction(key) { var actionKey = arguments[0]; //动作指令标识 if (!actionKey) { console.error('调用sendAction方法,需要将动作指令名称{string}作为第一个参数值'); return { "type": ReduxUtils.UNKNOW_ACTION_KEY }; } //除动作指令标识以外的其它参数 var actionArgs = []; for (var i = 1; i < arguments.length; i++) { actionArgs.push(arguments[i]); } //构建动作指令包 var newAction = {}; newAction.type = ReduxUtils.ACTION_KEY; newAction.actionKey = actionKey; newAction.actionArgs = actionArgs; return newAction; }

    可以看到,其实redux创建一个新的action,并不会直接把我们平时认为的”action名”给到返回对象的type字段上,而是给到了actionKey上,type字段是一个字符串常量。原因在后面会提到,方法的其它参数会封成一个数组,传给actionArgs字段。所以通过createAction封装出来的action会是这个样子:

    { type:"__REDUX_SEND_ACTION_DATA__", actionKey:"//真正的action指令名", acitonArgs:[/*action装载的数据*/] }

    三、通过createAction 创建出来的方法 如何被reducer层认识

    我们知道,一个action要被reducer层注册的方法认识并执行,普遍的实现方法就是:

    //一个reducer分支 export default const reducer = (state = { list:[] },action){ let newState = Object.assign({},state); switch(action.type){ case "INIT_LIST": newState.list = action.list; return newState; } }

    这种方式简单,但是有一个缺点,随着我们对一个reduce分支绑定的操作越来越多,这个switch/case就会显得特别冗长。所以我们来关注两个问题:

    1.怎样将这些case拆分到不同的文件或者方法中呢?

    2.结合createAction创建出来的,真实type在actionKey属性上,如何能被识别分发到绑定方法上?

    下面有一个很深的套路:

    看一下ReduxUtil提供的,监听action执行action对应方法的 listen方法

    //listen方法接收的actions参数: var actions = { "loadTable":function(prevState,tableData){ return assign({},prevState,{tableData:tableData}); }, "loadDetailTable":function (prevState,detailTableData) { return assign({},prevState,{detailTableData:detailTableData}); } } //ReduxUtil 提供的 listen方法 listen: function listen(actions) { return function () { //第一个参数就是初始的state var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; //第二个参数是action var action = arguments.length <= 1 || arguments[1] === undefined ? { type: type, actionKey: actionKey, actionArgs: [] } : arguments[1]; //有没有从接收参数的方式看出来这就是一个reducer if (action.type == ReduxUtils.ACTION_KEY) { //如果type是reduxUtil中那个静态常量,说明是ReduxUtil创建的action //所以通过action中的actionKey将对应方法取出来 var actionFunc = actions[action.actionKey]; if (isFunction(actionFunc)) { //将当前state和本动作相关的参数传递给动作处理函数 var callArgs = [state].concat(action.actionArgs); //获取动作处理函数返回的新状态 var newState = actionFunc.apply(this, callArgs); //如果动作处理函数无返回结果则返回原始状态,否则返回新状态 return newState == undefined ? state : newState; } else { return state; } } else { return state; } }; }

    将actions传入listen方法,就会得到一个reducer分支

    export default combineReducers({ routing: routerReducer, refinfo, sample: ReduxUtils.listen(actions) });

    总结:我们在书写reducer层代码的时候,只需要创建一个类似

    { "action绑定方法名": 处理方法 }

    这样的对象就可以了。要记住将这个对象通过ReduxUtils.listen注册到reducer树中。

    转载请注明原文地址: https://ju.6miu.com/read-8249.html

    最新回复(0)