redux原理解析
redux状态管理库向外暴露了六个API: createStore, combineReducers, applyMiddleware, bindActionCreators, componse,今天就来尝试通过手写其中的几个Api,来更加了解redux的工作机制
createStore
这个createStore是用来创建store对象的,用于保存状态树中的数据,且是唯一一个,createStore向外暴露了三个方法:getState(), subscribe, dispatch,那就赶紧动手来实现吧
export const createStore = (reducers, enhance) => {
let state = {}; // 状态数据
let listeners = []; // 收集listener
if (enhance) {
return enhance(createStore)(reducers); //返回增强后的store
}
const getState = () => { //获取store中的state数据的方法
return state;
};
const subscribe = (listener) => { // 变化监听器,每次dispatch的时候,都会去执行这个listener函数
listeners.push(listener);
}
const dispatch = (action) => { // 分发action,执行reducer操作,产生新的state数据
state = reducer(state, action);
listeners.forEach(l => l());
}
dispatch({type:'@INIT-REDUX'}); // 分发一个初始化的action
return {getState, subscribe, dispatch};
}
applyMiddleware(…middleware)
使用middleware的自定义方法来扩展redux, applyMiddleware可以让你包装store中的dispatch方法来达到你想要的目标,比如能够dispatch一个函数,能够处理异步操作
applyMiddleware(loggge, jdeid)
export const applyMiddleware = (...middlewares) => {
return createStore => (...reducers) => {
const store = createStore(...reducers);
let dispatch = store.dispatch
let middlewareApi = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
};
// 将多个middleware组成一个调用链,每个middleware接收两个参数:真实store的dispatch和getState方法调用链的最后一个接收真实store的diapatch方法作为参数,借此结束调用链
middlewareChain = middlewares.map(middleware => middleware(middlewareApi) );
// 增强store的dispatch方法
dispatch = compose(...middlewareChain)(dispatch);
return {
...store,
dispatch
}
}
}
componse
从左到右组合多个函数,将多个函数组合成一个函数
export const componse = (...fns) => {
if (fns.length === 0) {
return fn => fn
} else (fns.length === 1) {
return fns[0];
} else {
fns.reduce((prev, item) => (...args) => prev(item(...args)))
}
}
bindActionCreators
使用dispatch对每个action creator进行包装。以便后续直接调用
const bindActionCreator = (creator, dispatch) => {
return (...args) => dispatch(creator(...args))
}
const bindActionCreator = (creators, dispatch) => {
Object.keys(creators).reduce((ret, item) => {
ret[item] = bindActionCreator(creators[item], dispatch);
return ret
}, {})
}