1

redux源码详解

redux是基于flux单向数据流的一种实现,功能很强大,源码很精炼,可以扩展出各种中间件,so 酷。

createStore.js

这个文件其实很简单,首先我们来看一下它接受的参数。


function createStore(reducer, initialState){

}

这里的reducer就是 combineReducers后的rootReducer,当我们dispatch一个action的时候


function dispatch(action) {
    currentState = currentReducer(currentState, action)
}

currentReducer接受了两个参数,currentState,也就是当前的state。和我dispatch的action,当返回的action.type匹配到相应的reducer时,就会更新store。
在createStore.js文件的返回值中,最常用的应该是dispatch和getState()。
其中dispatch用来分发action到reducer从而更新store, 而getState() 方法则会拿到当前的store。

combineReducers.js

首先我们来讨论一下为什么会有这个文件。首先我们不会把整个项目的reducer都写在一个switch里。
所以我们可能会写多个reducer,但是当我们调用createStore()方法来生成store时,就会调用多个createStore。好的,这样问题就来了,不但会产生多个数据源,而且会有多个dispatch,getState()等等。
而combineReducer就是为了解决上面的一系列问题而存在的。


function combination(state=defaultState, action) {
    var finalState = mapValue(finalReducers, 
    (reducer, key) => {
        var previousStateForKey = state[key];
        var nextStateForKey = reducer(previousStateForKey, action);
        return nextStateForKey;
    })
    return finalState
}

这里只列出了主要的几行代码,其中mapValue()方法会把finalReducers的函数名映射到state[key]中,从而在整个store树中产生一个新的节点,所以reducer里面的state不再是全局的state而只是它的一个节点,这样当我们在reducer里更新state的时候不必在关心其它的reducer只关注自己当前的这个state就可以了。

applyMIddleware.js

关于applyMiddleware,就是调用中间件,听起来貌似很高大上,实际上的代码实现却是非常简单。
所谓中间件,就是将dispatch(action)和getState()方法不断的在中间件方法中传递,最后再传递给reducer。先来看一下代码实现。


function applyMiddleware(...middlewares) {
    var middlewareAPI = {
        getState = store.getState,
        dispatch: (action) => dispatch(action)
        chain = middlewares.map(middleware => middleware(middlewareAPI))
       dispatch = compose(...chain)(store.dispatch);
    }
}

其中compose是redux自己的一个工具函数

    

    function compose(...funcs) {
              return arg => funcs.reduceRight((composed, f) => f(composed), arg);
        }   

   

what?毛线啊这是?
读书少,没办法,要去看看复合函数和柯里化的概念了。
首先我们回过头来看一下这个方法的调用模式

    dispatch = compose(...chain)(store.dispatch);

其中store.dispatch参数就是compose方法中的age。
柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数而且返回结果的新函数的技术,这里正是用到了函数式编程的柯里化。举个例子

     

    function sum(num){ 
          return function (x){ 
          return num + x; 
             } 
         } 
         var sum1 = sum(1)(1); 
         var sum2 = sum(2)(1); 
         console.log(sum1); //2
         console.log(sum2); //3

回到主题,compose方法组合了我们的的中间件链
在redux中的中间件模式,可以让我们处理多种类型的action,当然其中最为常用的可能就是异步的action。先来看一下异步中间键reduxthunk的实现。
其调用模式类似于

middlewareA(middlewareB(middlewareC(store.dispatch)))(action)


function thunkMiddleware({ dispatch, getState }) {
  return next => action =>
    typeof action === 'function' ?
    action(dispatch, getState) :
    next(action);
}
module.exports = thunkMiddleware

骗子。。。当我兴致勃勃的去看源码的时候,整个库真的居然只有这么几行有用的代码,好吧,这里其实就是判断了action是不是一个function如果时的话就将dispatch和getState交给这个action来处理。

总结

其实吧,我一直都觉得redux的流程是很繁琐的,但是它的优点却是更加明显,single store使整个项目的数据结构更佳清晰。避免项目很大时,数据以及状态难以维护和管理情况。


wupengyu
1.8k 声望166 粉丝

写作是为了更好的思考