redux
项目目录:
redux基本数据流:
createStore
createStore(reducer:any,preloadedState?:any,enhancer?:middleware),最终返回一个
state tree实例。可以进行getState,subscribe监听和dispatch派发。(第二个参数可以传一个enhancer)
createStore 接收3个参数
- reducer:给定当前
state tree和要执行的action,返回下一个state tree。 - preloadedState,
initial state tree。 - enhancer, 增强器,若干个中间件可以通过 redux自带的
applymiddleware产生一个增强器enhancer,多个增强器可以通过compose函数合并成一个增强器。
enhancer实际作用就是自定义一个dispatch覆盖createStore返回的dispatch
const store = {
dispatch,
subscribe,
getState,
replaceReducer,
[?observable]: observable
}


getState

subscribe

这个函数实质的作用是确保可以改变nextListeners,如果nextListeners与currentListeners一致的话,将currentListeners做一个拷贝赋值给nextListeners,然后所有的操作都会集中在nextListeners,比如我们看订阅的函数subscribe:

subscribe函数以及返回的unsubcibe函数都是在nextListeners中进行操作。
const store = createStore(reducers.todos)
const unsubscribe1 = store.subscribe(() => {
const unsubscribe2 = store.subscribe(()=>{})
})
增加nextListener这个副本是为了避免在遍历listeners的过程中由于subscribe或者unsubscribe对listeners进行的修改而引起的某个listener被漏掉了。比如你在遍历到某个listener的时候,在这个listener中unsubscribe了一个在当前listener之前的listener,这个时候继续i ++的时候就会直接跳过当前listener的下一个listener,不知道有没有描述清楚
dispatch
- 状态位控制流程,在reducer过程中不允许dispatch
- 用快照的形式存储监听器列表,避免在监听器函数中调用subscribe函数引发的不可预期行为

combineReducers
combineReducers用来将若干个reducer合并成一个reducers,使用方式:
combineReducers({
key:(state = {}, action)=>{
return state
},
post:(state = {}, action)=>{
return state
}
})

applyMiddleware
- 如何让中间件都可以获取到state
- 如何让中间件可链式使用
compose

const a = str => str + 'a'
const b = str => str + 'b'
const c = str => str + 'c'
const compose = (...funcs) => {
return funcs.reduce((a,b)=>(...args)=>a(b(...args)))
}
compose(a,b,c)('初始参数')
// 约等于
a(b(c('初始参数')))// 初始参数cba
中间件的开发应该是这样的形式
// 返回的第一个函数是为了保证中间件可以取到全局状态,返回的第二个函数是为了保证中间件可以依次调用。
const someMidware = (store) => {
return (next) => {
return (action) => {
// dosometing
// next(action)
// dosometing
}
}
}
源码:
其中applyMiddleware形参和实参的对应关系是:
| 形参 | 实参 |
|---|---|
middlewares |
[middleware1,middleware2] |
createStore |
Redux原生createStore |
reducer, preloadedState, enhancer |
原生createStore需要填入的参数 |
| 再看函数体: |

所以经过applyMiddleware改造后的dispatch,用一个例子
const mid1 = store => next => action => { console.log(store); next(action) }
const mid2 = store => next => action => { console.log(store); next(action) }
middlewares = [mid1, mid2]
enhancer = (...middlewares) => (createStore) => (reducer, preloadedState, enhancer) => {
// 初始化store
var store = createStore(reducer, preloadedState, enhancer)
var chain = []
// 暂存改造前的store
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
// 通过闭包,每个中间件得到的都是同一个store即middlewareAPI。这样就保证了数据的迭代变化
chain = [mid1, mid2].map(middleware => middleware(middlewareAPI))
// chain = [mid1(middlewareAPI),mid2(middlewareAPI)]
// middleware(middlewareAPI) 应用中间件,chain中的每个中间件就变成
// 相当于 mid1 =(next)=>(action) =>{console.log(store); next(action)}
// mid2 =(next)=>(action) =>{console.log(store); next(action)}
dispatch = compose(...chain)(store.dispatch)
// dispatch === mid1(mid2(store.dispatch))
// 返回改造后的store
return {
...store,
dispatch
}
}
// 所以经过applyMiddleware改造后,每次dispatch一个actio的流程是这样的
mid1(mid2(store.dispatch))(action)
redux-Space


