欢迎关注redux源码分析系列文章:
redux源码分析之一:createStore.js
redux源码分析之二:combineReducers.js
redux源码分析之三:bindActionCreators.js
redux源码分析之四:compose.js
redux源码分析之五:applyMiddlewaregit
createStore.js是redux的核心文件,暴露了一个函数createStore,函数执行后返回一个对象,该对象包含了4个关键的方法:dispatch, subscribe, getState, replaceReducer,代码以下。github
export default function createStore(reducer, preloadedState, enhancer) { //中间代码略 return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable } }
//若是preloadedState没有传,可是enhancer参数传了,重置一下变量 if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState preloadedState = undefined } //若是enhancer传了,可是不是函数,则报错提示,不然执行enhancer函数, //并继续执行enhancer函数返回的增强版的createStore函数, //参数reducer以及preloadeState和原createStore函数保持一致 if (typeof enhancer !== 'undefined') { if (typeof enhancer !== 'function') { throw new Error('Expected the enhancer to be a function.') } return enhancer(createStore)(reducer, preloadedState) } //若是reducer不是函数,则报错 if (typeof reducer !== 'function') { throw new Error('Expected the reducer to be a function.') }
let currentReducer = reducer //保存了当前的reducer函数,该reducer函数能够被动态替换掉 let currentState = preloadedState //保存了当前的state数据 let currentListeners = [] //保存了当前注册的函数列表 let nextListeners = currentListeners let isDispatching = false //是否正在dispatch一个action
最关键的是currentState变量,调用createStore以后,currentState变量保存了当前状态的全部数据redux
//确保nextListeners和currentListeners不是同一个引用 function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { //若是是同一个引用,则浅拷贝currentListeners到nextListeners nextListeners = currentListeners.slice() } }
//getState函数,返回局部变量currentState,以获取当前状态 function getState() { return currentState }
//注册一个函数,将注册函数放入局部变量nextListeners数组里面 //注册函数的返回值是一个注销函数,注销函数执行能够将刚刚添加进nextListeners的listener函数又删除掉。这里颇有意思,外部必须在调用subscribe执行现场保存好unsubscribe函数,不然将没法注销一个函数 function subscribe(listener) { //若是listener不是函数,直接报错 if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } let isSubscribed = true //确保nextListeners不是currentListeners,以保证修改的是nextListeners,而不是currentListeners ensureCanMutateNextListeners() //将监听函数放入监听函数列表尾部 nextListeners.push(listener) //返回一个函数,该函数能够从监听函数列表中删除刚刚注册的监听函数 return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } }
//触发action的函数:每次触发一个action,currentListeners中的全部函数都要执行一遍 function dispatch(action) { //若是action不是普通的对象,直接报错 if (!isPlainObject(action)) { throw new Error( 'Actions must be plain objects. ' + 'Use custom middleware for async actions.' ) } //若是action没有type属性,直接报错:说明action对象必需要包含type字段 if (typeof action.type === 'undefined') { throw new Error( 'Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?' ) } //若是当前正在触发另一个action,直接报错 if (isDispatching) { throw new Error('Reducers may not dispatch actions.') } try { //先将标志位置为true isDispatching = true //执行传入的reducer函数,该函数返回一个新的state对象,并赋值给currentState变量 currentState = currentReducer(currentState, action) } finally { //reducer函数执行完成后,将isDispatching恢复成false,方便下次action的触发 isDispatching = false } //每一次触发一个action,全部的监听函数都要所有从新执行一遍, //而且把上次获得的新的监听函数列表赋值成为当前的监听函数列表。这是一个懒操做,并非在subscribe的时候就操做了,而是在dispatch的时候才操做 const listeners = currentListeners = nextListeners for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } //该dispatch函数的返回值是原来的action return action }
//替换reducer函数:这个函数容许运行时动态替换最开始调用createStore函数时传入的reducer,而且替换掉reducer以后,从新dispatch一个action,获得全新的currentState对象 function replaceReducer(nextReducer) { //若是nextReducer不是函数,直接报错 if (typeof nextReducer !== 'function') { throw new Error('Expected the nextReducer to be a function.') } //把新的reducer赋值给当前的currentReducer变量,获得一个全新的currentReducer currentReducer = nextReducer // 触发一个初始action: // 1.这样就能够完成一次监听函数列表的所有调用 // 2.能够获得一个全新的currentState; dispatch({type: ActionTypes.INIT}) }
function observable() { const outerSubscribe = subscribe return { /** * The minimal observable subscription method. * @param {Object} observer Any object that can be used as an observer. * The observer object should have a `next` method. * @returns {subscription} An object with an `unsubscribe` method that can * be used to unsubscribe the observable from the store, and prevent further * emission of values from the observable. */ subscribe(observer) { if (typeof observer !== 'object') { throw new TypeError('Expected the observer to be an object.') } function observeState() { if (observer.next) { observer.next(getState()) } } observeState() const unsubscribe = outerSubscribe(observeState) return {unsubscribe} }, [$$observable]() { return this } } }
初始化很简单,一句代码,直接调用一次dispatch,就会执行全部的注册函数,而且执行reducer函数,生成初始化的statesegmentfault
//立刻内部调用一次初始化的操做,根据传入的reducer函数,preloadedState生成一个全新的currentState和全新的reducer dispatch({type: ActionTypes.INIT})
总结一下就是:数组
完整解析请参考个人github:https://github.com/abczhijia/...,若是对您有帮助,欢迎star,有任何问题也请指正。app
(完)async