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使整个项目的数据结构更佳清晰。避免项目很大时,数据以及状态难以维护和管理情况。