redux并不局限于flux与react。redux 自身保持简洁以便适配各类场景,让社区发展出各类 redux-* 中间件或者插件,从而造成它本身的生态系统。html
reducer 声明了state的初始值,以及当前state接受action对象以后处理为new state的逻辑。react
createStore接受reducer做为参数,返回产生的store,store实际上是一个含有state的闭包,以及提供将action分发给reducer的dispatch方法。git
applyMiddlewares方法接受n个middlewares做为参数返回一个用于渲染creatorStore函数的方法。github
applyMiddleware能够向actionCreator提供store.dispatch以及getState方法,用以加强actionCreator的能力redux
store主要包含如下三个核心方法:数组
subscribe 注册store更新以后的回调函数promise
getState 获取store当前state的引用,切记直接修改返回的结果缓存
dispatch 将action按顺序通过各middle处理后派发给reducer闭包
createStore是根据reducer中的规则建立store的方法。app
提供dispatch
subscribe
getState // getState拿到的是state的引用!不要直接修改
提供初始值initialState
//此处为示意,不是 redux 的源码自己 export default createStore(reducer, initialState) { //闭包私有变量 let currentState = initialState let currentReducer = reducer let listeners = [] //返回一个包含可访问闭包变量的公有方法 return { getState() { return currentState //返回当前 state }, subscribe(listener) { let index = listeners.length listeners.push(listener) //缓存 listener return () => listeners.splice(i, 1) //返回删除该 listener 的函数 }, dispatch(action) { //更新 currentState currentState = currentReducer(currentState, action) // 能够看到这里并无用到eventEmitter等 listeners.slice().forEach(listener => listener()) return action //返回 action 对象 } } }
action有如下特色:
pure object
描述reducer响应的事件类型
携带所须要的数据
用于描述action的dispatch的逻辑。
action的重用
数据的预处理
action的特殊处理逻辑
reducer应该是是一个无反作用函数,以当前的state以及action为参数,返回新的state。
每次返回一个新State的好处是在shouldComponentUpdate过程当中可使用高性能的shallow equal。
pure function
接受initialState
don't modify the state!!!
//reducer 接受两个参数,全局数据对象 state 以及 action 函数返回的 action 对象 //返回新的全局数据对象 new state export default (state, action) => { switch (action.type) { case A: return handleA(state) case B: return handleB(state) case C: return handleC(state) default: return state //若是没有匹配上就直接返回原 state } }
将一个reducer map转换为一个reducer。方便对复杂的reducer进行功能拆分。
state 结构太复杂
但愿根据对应的component进行维护
var reducers = { todos: (state, action) { //预期此处的 state 参数是全局 state.todos 属性 switch (action.type) {...} //返回的 new state 更新到全局 state.todos 属性中 }, activeFilter: (state, action) { //预期拿到 state.activeFilter 做为此处的 state switch (action.type) {...} //new state 更新到全局 state.activeFilter 属性中 } } //返回一个 rootReducer 函数 //在内部将 reducers.todos 函数的返回值,挂到 state.todos 中 //在内部将 reducers.activeFilter 函数的返回值,挂到 state.activeFilter 中 var rootReducer = combineReducers(reducers)
//combination 函数是 combineReducers(reducers) 的返回值,它是真正的 rootReducer //finalReducers 是 combineReducers(reducers) 的 reducers 对象去掉非函数属性的产物 //mapValue 把 finalReducers 对象里的函数,映射到相同 key 值的新对象中 function combination(state = defaultState, action) { var finalState = mapValues(finalReducers, (reducer, key) => { var newState = reducer(state[key], action); //这里调用子 reducer if (typeof newState === 'undefined') { throw new Error(getErrorMessage(key, action)); } return newState; //返回新的子 state }); //...省略一些业务无关的代码 return finalState; //返回新 state }; function mapValues(obj, fn) { return Object.keys(obj).reduce((result, key) => { result[key] = fn(obj[key], key); return result; }, {}); }
异步action
promise
个性化 action 响应
log
接受 middleWares 将 store 修饰为使用了 middlwares 的 store,实际上是用被高阶函数修饰过的dispatch替换掉了原来的dispatch。
var craeteStoreWithMiddleWare = applyMiddleWare(thunk)(createStore); //redux-thunk export default function thunkMiddleware({ dispatch, getState }) { return next => action => typeof action === 'function' ? // action 竟然是函数而不是 plain object? action(dispatch, getState) : //在中间件里消化掉,让该函数控制 dispatch 时机 next(action); //不然调用 next 让其余中间件处理其余类型的 action }
这里的composeMiddleware可能不是很好理解,这里有一个简单的例子方便你们理解。http://jsbin.com/xalunadofa/1/edit?js,console。 compose能够理解为倒叙一层层打包的过程,所以最后调用composedFunction的时候会顺序进入各个middlewares。
function applyMiddleware(...middlewares) { return next => (...args) => { const store = next(...args); const middleware = composeMiddleware(...middlewares); // dispatch 被middlWare修饰 function dispatch(action) { const methods = { dispatch, getState: store.getState }; return compose( middleware(methods), store.dispatch )(action); } // 返回新的store dispatch被新的dispatch替代 return { ...store, dispatch }; }; }
//将 actionCreator 跟 dispatch 绑定在一块儿 let bindActionCreator => (actionCreator, dispatch) { return (...args) => dispatch(actionCreator(...args)); } function bindActionCreators(actionCreators, dispatch) { if (typeof actionCreators === 'function') { //若是是单个 actionCreator,绑定一词 return bindActionCreator(actionCreators, dispatch); } //返回一个改造过的「函数组合」 return mapValues(actionCreators, actionCreator => bindActionCreator(actionCreator, dispatch) ) }
connector 接受mapStateToProps, mapDispatchToProps, Component 三个参数,返回一个可以自动关联store中state以及dispatch事件的smart component
因为connector代码过长,只对重要的几个函数进行说明。
connetor函数接受的两个参数指明从store的state中挑选哪些做为props,以及将哪些actionCreator绑定到porps中。
订阅store的change事件,当store更新时计算新的state,与旧state进行浅对比,若是不一样则更新state,并render,不然不进行render。
// 根据从store中select的state以及dispatch绑定的actionCreator计算新的props computeNextState(props = this.props) { return computeNextState( this.stateProps, this.dispatchProps, props ); } // 与旧值进行shallow equal updateState(props = this.props) { const nextState = this.computeNextState(props); if (!shallowEqual(nextState, this.state.props)) { this.setState({ props: nextState }); } } // 订阅change事件 trySubscribe() { if (shouldSubscribe && !this.unsubscribe) { this.unsubscribe = this.store.subscribe(::this.handleChange); this.handleChange(); } } tryUnsubscribe() { if (this.unsubscribe) { this.unsubscribe(); this.unsubscribe = null; } } componentDidMount() { this.trySubscribe(); } componentWillUnmount() { this.tryUnsubscribe(); } handleChange() { if (!this.unsubscribe) { return; } if (this.updateStateProps()) { this.updateState(); } }
欢迎你们发起pr完善文档,进行讨论。