整个redux的源码非常简单,所以解释很少,看代码就能看明白......
combineReducers
为啥先说这个
前提先看middleware: Redux-Middleware-源码解析, 这些都是解析createStore的前提
//传入的reducers是个对象
//将多个reducer捆成一个
export default function combineReducers(reducers) {
//取出所有reducer的key=> {key1:value,key2:value}
const reducerKeys = Object.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 = Object.keys(finalReducers)
let shapeAssertionError
try {
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e
}
//返回一个 combination 函数,方法接收state,action参数 这个返回的函数是createStore的第一个参数
return function combination(state = {}, action) {
if (shapeAssertionError) {
throw shapeAssertionError
}
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,且只有一个store
export 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 = Object.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