为什么需要多个reducer
如果只有一个reducer,就代表状态管理树的状态只有一个对象,即state.
但是一个应用就像一本书,每一页都应该有自己的数据,所以仅仅有一个state是不足的,代码形式上也不够优雅
const initialState = {
myList : [
'你他妈是不是脑袋有泡',
'你他妈是不是脑袋有泡',
'你他妈是不是脑袋有泡'
]
}
const reducer = (state = initialState,action)=> {
switch(action.type) {
case myAction.CAONIMA : {
state.myList = state.myList.map(item=>(action.payload))
return state
}
default : {
return state
}
}
}
单一reducer,每次dispatch action后,都会更新currentState 然后通知所有订阅接口
try {
isDispatching = true
// 使用reducer 处理传入的action
currentState = currentReducer(currentState,action)
} finally {
isDispatching = false
}
currentListeners = nextListeners
const listeners = currentListeners
let index = -1
// 遍历订阅的接口
while(++index<listeners.length) {
const listener = listeners[index]
listener()
}
谈谈combineReducers
combineReducers接受一个字典,键为reducers的名字,值为reducer本身.
最后闭包缓存了这些reducers,最终并返回一个新的reducer函数
combineReducers({
reducer1,
reducer2
})
引入之后,state初始化就应该是这种形式
state = {
reducer1 : reducer1(),
reducer2 : reducer2()
}
事实上,他内部也是如此
return function combination(state = {}, action) {
// finalReducers为传入的reducers对象
const finalReducerKeys = Object.keys(finalReducers)
// 下一次执行reducer 存放结果的集合
const nextState = {}
// 遍历 这意味着派发的action会触发所有的reducers
for(let i=0;i < finalReducerKeys.length;i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
// 缓存上一次的reducer状态
const previousStateForKey = state[key]
// 触发reducer获取状态
const nextStateForKey = reducer(previousStateForKey,action)
if(typeof nextStateForKey === 'undefined') {
throw new Error(`key为${key}的reducer在处理${action.type}时 返回了一个空的state`)
}
nextState[key] = nextStateForKey
// 如果这个reducer返回的state的地址与原有state的地址不一样 则赋值给hasChanged
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
// 如果有一个reducer的state地址变了,则返回新的nextState,否则返回state
return hasChanged ? nextState : state
}
实战演习
const initState1 = {
meta : '树1'
}
const initState2 = {
meta : '树2'
}
const reducer1 = (state=initState1,action)=> {
switch(action.type) {
default : return state
}
}
const reducer2 = (state=initState2,action)=> {
switch(action.type) {
case 'AAAAAA' : {
state.meta = action.payload
return state
}
default : return state
}
}
export default createStore(combineReducers({
reducer1 : reducer1,
reducer2 : reducer2,
}))
在某个组件中
onClickHandler() {
store.dispatch({
type : 'AAAAAA',
payload : "我妈妈在看直播 你们别骂了"
})
}
点击之后派发action,就会更新state,虽然没有改变state的地址,但还是会触发所有订阅store的接口,通知state发生了改变
![](https://img.haomeiwen.com/i16287067/2196e4d9d4eb91a9.png)
网友评论