整个redux的源码非常简单,所以解释很少,看代码就能看明白......
combineReducers
为啥先说这个
前提先看middleware: Redux-Middleware-源码解析, 这些都是解析createStore的前提
//传入的reducers是个对象//将多个reducer捆成一个export default function combineReducers(reducers) { //取出所有reducer的key=> {key1:value,key2:value} const reducerKeys = .keys(reducers) const finalReducers = {} for (let i = 0; i < reducerKeys.length; i++) { //取出key const key = reducerKeys[i] if (typeof reducers[key] === 'function') { //可以代表的value是函数的话,保存进 finalReducers 对象中 finalReducers[key] = reducers[key] } } //取出所有value是函数的key const finalReducerKeys = .keys(finalReducers) let shapeAsserti try { assertReducerShape(finalReducers) } catch (e) { shapeAsserti = e } //返回一个 combination 函数,方法接收state,action参数 这个返回的函数是createStore的第一个参数 return function combination(state = {}, action) { if (shapeAsserti ) { throw shapeAsserti } let hasChanged = false const nextState = {} //循环每一个reducer, for (let i = 0; i < finalReducerKeys.length; i++) { //取出key const key = finalReducerKeys[i] //取出key对应的reducer const reducer = finalReducers[key] //根据key在state获取状态 //state的状态都是根据reducer的名字进行存储的 const previousStateForKey = state[key] //将state和action传入reducer中 const nextStateForKey = reducer(previousStateForKey, action) //将nextStateForKey reducer 放入到nextState中 nextState[key] = nextStateForKey //在state中的状态和reducer中返回的状态是否一样 hasChanged = hasChanged || nextStateForKey !== previousStateForKey } //返回新的state return hasChanged ? nextState : state }}是什么
- 名字的含义就是组合reducer
- 因为reducers是作为createStore函数的第一个参数,而不是前多少个参数
干了什么
export default combineReducers({ userinfo, stores, home, likeList})- 其中的每一个参数都是一个reducer,而且每一个参数的名字都作为在store中的key
- 将这些reducer组合成一个reducers,提供给createStore作为参数
流程啥样
- 虽然传了很多reducer但是先过滤掉不是function的reducer(不知道不是function的reducer是啥)
- 将过滤的key存放到finalReducerKeys中,将过滤的reducer存放到finalReducers中,闭包要用
- 然后返回一个 combination() 函数,其实这个才是createStore的第一个参数
combination做了什么
- 循环每一个有效的reducer
- 取出reducer,state中的对应的状态
- 调用reducer,并传入取出的状态,和action,获取返回值(新state)
- 返回新的state
createStore
//创建store的api,也是redux中最重要的api,而创建的store用于管理应用中的所有state,且只有一个storeexport default function createStore(reducer, preloadedState, enhancer) { //简而言之,第二个参数是函数,并且第三个参数是undefined,然后第二第三个参数值互换 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== 'undefined') { //这个就是中间件,看middleware那篇文章 return enhancer(createStore)(reducer, preloadedState) } //保存当前的reducer let currentReducer = reducer //保存传入的状态 let currentState = preloadedState //设置当前监听集合 let currentListeners = [] //将当前的监听集合赋值给下一个监听集合 let nextListeners = currentListeners let isDispatching = false function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { //slice() 没有参数默认begin为0 就是拷贝下 nextListeners = currentListeners.slice() } } //获取当前状态 //函数嵌套函数,内部函数引用外部函数的变量,最后返回函数,这是闭包 function getState() { return currentState } //增加监听,参数listener是一个回调函数,在dispatch里,会调用所有的监听器 function subscribe(listener) { let isSubscribed = true ensureCanMutateNextListeners() //把新增加的监听加入到当前监听列表中 nextListeners.push(listener) //返回一个函数,用于去除监听 return function unsubscribe() { if (!isSubscribed) { return } //解除监听 isSubscribed 设置为false,意为已经取消监听 isSubscribed = false ensureCanMutateNextListeners() const index = nextListeners.indexOf(listener) //然后干掉这个监听 nextListeners.splice(index, 1) } } //这个是比较常用的api=>主要用于触发action,改变状态 function dispatch(action) { try { isDispatching = true//正在dispatch //执行reducer 返回新state,调用的是combination()方法 currentState = currentReducer(currentState, action) } finally { // finally不管报没报错最后都要执行 isDispatching = false } //执行所有监听 const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action } //替换reducer 然后更新store function replaceReducer(nextReducer) { currentReducer = nextReducer dispatch({ type: ActionTypes.REPLACE }) } //这个是留给内部 function observable() { const outerSubscribe = subscribe return { subscribe(observer) { function observeState() { if (observer.next) { observer.next(getState()) } } observeState() const unsubscribe = outerSubscribe(observeState) return { unsubscribe } }, [$$observable]() { return this } } } //初始化store dispatch({ type: ActionTypes.INIT }) return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable }}是什么
- 这个是最核心的api,这个函数是创建store的唯一方式
- 并且返回了dispatch,subscribe,getState...比较常用的api
干了什么
const store = createStore(rootReducer, applyMiddleware(...middlewares));复制代码- 如果有中间件,先处理中间件然后回过头来在执行createStore
- 保存了一些当前的属性,用于闭包,提供的api
api
getState
这个直接返回了当前的state,因为闭包,所以可以获取到最新的state
subscribe
负责新增监听,参数是个回调函数,将回调函数加入到监听集合,并且返回一个取消监听的函数:这个返回的函数内部封装了当执行时,在监听集合中将这个监听去掉
dispatch
是最核心的api,通过执行reducer(闭包,currentReducer),返回新的state,并赋值给当前的currentState,并执行所有的监听,返回action
replaceReducer
用于替换reducer,然后调用dispatch更新state
bindActionCreators
这个结合connect使用,在mapDispatchToProps中定义,就可以直接用this.props.userInfoActions来调用dispatch(action)操作
function mapStateToProps( state ) { return {}}function mapDispatchToProps( dispatch ) { return { userInfoActions : bindActionCreators(userInfoActionsFormOtherFile, dispatch) }}export default connect( mapStateToProps, mapDispatchToProps)(App)复制代码function bindActionCreator(actionCreator, dispatch) { return function() { return dispatch(actionCreator.apply(this, arguments)) }}export default function bindActionCreators(actionCreators, dispatch) { //如果 actionCreators 是一个函数,染回 dispatch(actionCreator.apply(this, arguments)) if (typeof actionCreators === 'function') { return bindActionCreator(actionCreators, dispatch) } //actionCreators 不是函数,不是对象,不是null const keys = .keys(actionCreators) const boundActionCreators = {} for (let i = 0; i < keys.length; i++) { const key = keys[i] const actionCreator = actionCreators[key] if (typeof actionCreator === 'function') { boundActionCreators[key] = bindActionCreator(actionCreator, dispatch) } } //最后迭代actionCreators里的元素,如果是函数,就按照函数的方式组成数组,返回 return boundActionCreators}是什么
就跟名字一样:给actionCreators绑定dispatch,也就是返回一个dispatch(actionCreator.apply(this, arguments))这样的函数,或者包含多个dispatch的数组
干了什么
- 传入两个参数,第一个是actionCreator,第二个是dispatch
- 如果只是一个actionCreator,那么直接返回一个包含dispatch(actionCreator.apply(this, arguments))的函数
- 如果他是个数组,就去循环这个数组将每一个actionCreator都绑定dispatch,然后返回这个数组
总结
看完了源码,感觉redux真的没有太多的东西,真是映射了那句话:用尽量少的代码,做尽量多的事情!
combineReducers
- 参数reducers是一个多个reducer组合的对象
- 去除所有的reducer的key=> reducerKeys
- 循环reducerKeys通过key取出reducer
- 如果reducer是个函数,就加进 finalReducers 中
- 取出finalReducers中的所有key=>finalReducerKeys
- 然后返回combination,这个是个内部函数,里面用到了上面的finalReducers和finalReducerKeys
- combination中取出每个reducer,根据finalReducerKeys中对应的key,在state中取出响应的状态
- 执行reducer并将参数传入返回新状态
- 将返回的状态添加进nextState对象中
- 返回新状态
通过代码的执行总结combineReducers
- 将多个reducer的对象reducers传入combineReducers中
- 返回 combination函数
- 返回的函数作为createStore的第一个参数
- 进入createStore中,提供的dispatch()中用到了reducers,并传入了state和action
- 然后执行combination函数,循环finalReducers
- 执行每一个reducer,通过返回的state,并添加进nextState对象中
- 返回的state和参数的state比较,如果两个state相等,则说明这个key所对应的state没有变化
- 如果不相等说明有变化,标记有变化
- 最后根据state是否有变化决定返回 nextState 还是参数 state
原文作者:mazy
继续阅读与本文标签相同的文章
-
玩烂 Vuex
2026-06-02栏目: 教程
-
美团外卖iOS多端复用的推动、支撑与思考
2026-06-02栏目: 教程
-
前端不止:Web性能优化 – 关键渲染路径以及优化策略
2026-06-02栏目: 教程
-
荷兰将推出全球首个混凝土逐层3D打印住宅区
2026-06-02栏目: 教程
-
探索 JS 中的模块化
2026-06-02栏目: 教程
