createStore是一个高阶函数,主要作用是完成store的初始化
createStore(reducer,preloadedState,enhancer)
export default function createStore(reducer, preloadedState, enhancer) { // 只传两个参数并且第二个参数是函数的情况下,将其作为增强函数enhancer, 如createStore(reducer,applyMiddleware(middleWare)) if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) } let currentReducer = reducer let currentState = preloadedState // 通过闭包维持一份createStore的state tree,更新时,current指针将指向dispatch生成的new state tree, 通过getStateapi对外暴露最新的state tree let currentListeners = [] // subscribe方法收集的订阅 let nextListeners = currentListeners // 用于调用ensureCanMutateNextListeners 浅拷贝一份list,防止用户在dispatching时调用subscribe/unsubscribe出现bug let isDispatching = false // 是否正在更新state function dispatch(action) { try { isDispatching = true // 改变当前状态 currentState = currentReducer(currentState, action) } finally { isDispatching = false } // 在dispatch改变当前状态之后立即执行所有通过subscribe的函数,执行listener主要用于在更新状态之后做些什么事情,比如视图的render操作,我们可以根据最新的状态去渲染视图 // 这种方式有一个缺点就是,不论你消费的数据有没有变化,只要你使用subscribe订阅了store,都会执行订阅函数 // 也就是说,redux并不识别具体的订阅者,而是统一广播通知,但这一功能被react-redux实现了 const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action } dispatch({ type: ActionTypes.INIT }) // 执行createStore完成状态初始化的时候,会在内部调用dispatch传递一个type为init的action, 并且返回一个store对象, 这也是唯一的一次非用户生成的action调度 return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable } }
createStore的几个主要api
- dispatch
- subscribe/unsubscribe
- getState
dispatch
负责响应用户的动作,派发action给reducer从而获取最新的视图状态
dispatch在初始化的时候由redux自身调用一次init action,其他时候都是用户由派发action调用
流程:
- dispatch将store的currentState指针指向reducer返回的new state
- 向用户广播通过subscribe注册的所有订阅
- 通过getState向用户暴露currentState
function dispatch(action) { try { isDispatching = true currentState = currentReducer(currentState, action) } finally { isDispatching = false } const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action }
subscribe
store.subscribe(listener)
订阅redux 状态变化,一旦状态发生变化就执行所有的订阅函数,同时返回一个取消订阅的函数unsubscribe
function subscribe(listener) { let isSubscribed = true nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) currentListeners = null } }
getState
createStore通过闭包维持一份state tree。
状态更新时, currentState指针将指向dispatch生成的new state tree, 并通过getState向外暴露
function getState() { if (isDispatching) { throw new Error( 'You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.' ) } return currentState }