由于这段时间一直很忙,所以本想六月初研究完redux源码就写一篇博客记录一下自己的心得,但一直现在才空闲出来,废话不多说了,直接说主题吧。
背景:
如今在如此复杂的前端交互和逻辑中,如果是单靠UI框架(react,vue,angular)是远远不够的,还需要一个对内部的数据状态进行管理的机制才行,而对于这种数据管理机制如今较为热门是主要有几个:redux,vuex,mobx;这次主要讲述的就是对redux源码进行分析。
摘要:
redux主要分为有几个主要的api:createStore,combineReducer,applyMiddleWare,compose;本博客就这四个api进行较为详细的分析和阐述,以及个人的见解;
redux原理图:
redux结构图:
- createStore
1)充分利用了高阶函数的特点,因为enchancer本身就将一系列中间件作为applymiddlewear第一个参数,然后只要判断enchancer是函数,就将createStore,reducer,preloadState分别传进去,最终返回一个对象,充分利用了applyMiddleWear和createStore这两者的嵌套。
2)就是个人觉得createStore直接返回一个字面量对象,对于单例模式来说不太严谨,因为单例模型就是一处创建,多处再创建都是只返回第一次的实例,这和angular中的server(服务)依赖注入不太像。
3)subscribe注册的listener不是针对于有个action的,所以多处地方注册,只要一个dispath,不相干的listener都会执行;
- combineReducer
注意点:
- 更新一次state,相当于遍历了一次所有的reducer,但往往只有一个地方要改变,这造成了性能的不好:
- combination(state = {}, action)中的state必须和reducers对象结构一致,就是说createStore中的initState必须和reducers一致;
- compose
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
解析:
因为middleware(简称MW)是一个数组,而要对store中的dispatch增强,必须将这些MW合成一个高阶复合函数,形式为a ( b ( c ( d ( params ) ) ) );其中MW从左到右依次嵌套,左边的MW是右边MW的
外层函数包;
例如:现有MW数组[ A, B, D];将这些MW合成一个函数;[ A, B, D].reduce((a, b) => (...args) => a(b(...args)))的过程为:
第一次:(A, B) => (...args) => a(b(...args)) ;假设返回的结果设为fn;则 fn = (...args) => A ( B ( args ) );
第二次:(fn, D) => (...args) => a(b(...args)) ; 假设返回的结果设为fn1;则 fn1 = (...args) => fn ( D ( args ) );
最后返回的是 fn1 = (...args)=> A ( B ( D ( args ) ) );
所以在applyMiddleware源码中,就有一句是:dispatch = compose(...chain)(store.dispatch);
则套用上面的例子,dispatch = A ( B ( D ( store.dispatch ) ) );
总结:本博客主要是针对源码进行流程上的解说和一些个人研究后的开发,下篇会简单介绍一下redux-react,特别是里面的一些坑。