import isPlainObject from 'lodash/isPlainObject' import $$observable from 'symbol-observable' /** * These are private action types reserved by Redux. * For any unknown actions, you must return the current state. * If the current state is undefined, you must return the initial state. * Do not reference these action types directly in your code. * * 这些都是redux自己预置的私有action types * 对于任何未知的action, 你必定要return当前的state. * 若是当前的state是undefined, 你必定要return最初始的state. * 必定,必定,必定不要在代码中直接引用action types . */ export const ActionTypes = { //初始化action的type,没有action参数的时候用 INIT: '@@redux/INIT' } /** * Creates a Redux store that holds the state tree. * The only way to change the data in the store is to call `dispatch()` on it. * There should only be a single store in your app. To specify how different * parts of the state tree respond to actions, you may combine several reducers * into a single reducer function by using `combineReducers`. * * 建立一个包含state tree(状态树)的redux store. * 惟一改变store中data(数据)的方法是调用`dispatch()`方法. * 在你的程序中应该只存在惟一一个store, 来代表state tree各部分怎样对action作出反应 * 你可能须要将多个reducer用`combineReducers`组合在一块儿 * * @param {Function} reducer A function that returns the next state tree, given * the current state tree and the action to handle. * * @param {Function} reducer 参数reducer是一个返回下一个state tree(状态树)的函数,来操做当前的state和action * * @param {any} [preloadedState] The initial state. You may optionally specify it * to hydrate the state from the server in universal apps, or to restore a * previously serialized user session. * If you use `combineReducers` to produce the root reducer function, this must be * an object with the same shape as `combineReducers` keys. * * @param {any} [preloadedState] 初始化的state,可选参数,你能够在universal(通常的,广泛的,我不知道怎么说比较合适) * 的程序中与服务器的state结合,或者restore一个预先连续的user session(直译过来的,通常用不到) * 若是你用`combineReducers`产生一个根reducer函数,这必定是一个和`combineReducers`的key同样的对象(根reducer是一个对象) * * @param {Function} [enhancer] The store enhancer. You may optionally specify it * to enhance the store with third-party capabilities such as middleware, * time travel, persistence, etc. The only store enhancer that ships with Redux * is `applyMiddleware()`. * * @param {Function} [enhancer] store加强器. 可选参数.用来加强第三方库的能力集(这个词是直译), * 好比中间件,时空穿越,和持续性(也是直译).redux的store加强器是`applyMiddleware()` * * @returns {Store} A Redux store that lets you read the state, dispatch actions * and subscribe to changes. * * @returns {Store} 返回值 一个redux的store,让你能够读取state, dispatch actions 和订阅更改 */ //createStore的目的只是建立一个store,这个store包含5个方法(通常只用到3个,最经常使用的是dispatch) export default function createStore(reducer, preloadedState, enhancer) { 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.')//指望enhancer是个函数 } // 当enhancer是函数的时候返回,而后执行,并将createStore做为参数传入,而后createStore就在enhancer里面 //去执行了 return enhancer(createStore)(reducer, preloadedState) } if (typeof reducer !== 'function') { throw new Error('Expected the reducer to be a function.') } let currentReducer = reducer //通常此reducer不是单个的reducer函数,而是combineReducers函数 let currentState = preloadedState let currentListeners = [] //监听函数 let nextListeners = currentListeners let isDispatching = false function ensureCanMutateNextListeners() { //nextListeners不是currentListeners if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } /** * Reads the state tree managed by the store. * * 读取被store管理的state树 * * @returns {any} The current state tree of your application. * *返回你的程序的当前的state树 */ function getState() { return currentState } /** * Adds a change listener. It will be called any time an action is dispatched, * and some part of the state tree may potentially have changed. You may then * call `getState()` to read the current state tree inside the callback. * * 添加一个改变事件,任什么时候候一个action被dispatch这个事件就会被调用,而后state树的某一部分就 * 会改变. 你也能够在回调函数里面调用`getState()`来查看当前的state树 * * You may call `dispatch()` from a change listener, with the following * caveats: * * 如下几种状况你也能够调用`dispatch()` * * 1. The subscriptions are snapshotted just before every `dispatch()` call. * If you subscribe or unsubscribe while the listeners are being invoked, this * will not have any effect on the `dispatch()` that is currently in progress. * However, the next `dispatch()` call, whether nested or not, will use a more * recent snapshot of the subscription list. * * 每次调用`dispatch`以前,订阅都会被snapshot, * 当事件被触发的时候你订阅或者不订阅,在当前的进程中都不会对`dispatch`有什么影响 * 然而当下一次`dispatch`被调用时,不管嵌套与否,将会使用最近的订阅列表的snapshot * * 2. The listener should not expect to see all state changes, as the state * might have been updated multiple times during a nested `dispatch()` before * the listener is called. It is, however, guaranteed that all subscribers * registered before the `dispatch()` started will be called with the latest * state by the time it exits. * * 不要期待监听事件能够看到全部的状态改变,由于在事件被调用前,state在嵌套的`dispatch`间 * 可能已经更新了不少次 * * @param {Function} listener A callback to be invoked on every dispatch. * 每次dispatch都会被出发的回调函数 * * @returns {Function} A function to remove this change listener. * 返回一个移除该事件的函数 */ function subscribe(listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } let isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) //添加事件到nextListeners数组 return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) //从nextListeners数组中移除事件 } } /** * Dispatches an action. It is the only way to trigger a state change. * * dispatch action是惟一触发state改变的途径 * * The `reducer` function, used to create the store, will be called with the * current state tree and the given `action`. Its return value will * be considered the **next** state of the tree, and the change listeners * will be notified. * * `reducer`函数,被用来建立store,有当前的state树和action就会被调用(state和action是reducer函数的参数) * 它的返回值会被当作下一个state树.监听事件会注意到state树的改变 * * The base implementation only supports plain object actions. If you want to * dispatch a Promise, an Observable, a thunk, or something else, you need to * wrap your store creating function into the corresponding middleware. For * example, see the documentation for the `redux-thunk` package. Even the * middleware will eventually dispatch plain object actions using this method. * * 最基本的用法是仅支持 为纯对象的 action,若是你想要dispatch一个promise,一个Observable, * thunk,或是其余东西,你须要封装store建立一个进入到相应中间件的函数. 好比,看一个`redux-thunk` * 的文档,即便是中间件最终也会用这个方法dispatch 纯对象的action * * @param {Object} action A plain object representing “what changed”. It is * a good idea to keep actions serializable so you can record and replay user * sessions, or use the time travelling `redux-devtools`. An action must have * a `type` property which may not be `undefined`. It is a good idea to use * string constants for action types. * * action是一个纯对象,表明'什么被改变了'. 保持action的连续性是个好主意,这样你就能够记录和 * 重现user session,或者使用时空穿梭`redux-devtools`. * action必须包含一个`type`属性,即便是`undefined`. 一般使用字符串常量表示 * * @returns {Object} For convenience, the same action object you dispatched. * * 为了方便,返回你dispatch的action * * Note that, if you use a custom middleware, it may wrap `dispatch()` to * return something else (for example, a Promise you can await). * 注意 若是你想使用特定的中间件,可封装`dispatch`返回其余东西(好比, 一个异步调用的promise) * */ function dispatch(action) { if (!isPlainObject(action)) { throw new Error( 'Actions must be plain objects. ' + 'Use custom middleware for async actions.' )//actions必须为纯对象,使用特定中间件异步调用actions } if (typeof action.type === 'undefined') { throw new Error( 'Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?' )//actions可能有一个未定义的type属性,你可能拼错了这个常量 } if (isDispatching) { throw new Error('Reducers may not dispatch actions.')//reducer没有dispatch action } try { isDispatching = true //dispatch的目的就是改变currentState currentState = currentReducer(currentState, action) //currentReducer = reducer } finally { isDispatching = false } const listeners = currentListeners = nextListeners //订阅函数的事件 for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action } /** * Replaces the reducer currently used by the store to calculate the state. * * 替换 store 当前用来计算 state 的 reducer。 * * You might need this if your app implements code splitting and you want to * load some of the reducers dynamically. You might also need this if you * implement a hot reloading mechanism for Redux. * * 这是一个高级 API。只有在你须要实现代码分隔,并且须要当即加载一些 reducer 的时候才可能会用到它。 *在实现 Redux 热加载机制的时候也可能会用到 * * @param {Function} nextReducer The reducer for the store to use instead. * store所替换的reducer * @returns {void} */ function replaceReducer(nextReducer) { if (typeof nextReducer !== 'function') { throw new Error('Expected the nextReducer to be a function.') } currentReducer = nextReducer dispatch({ type: ActionTypes.INIT }) } /** * Interoperability point for observable/reactive libraries. * @returns {observable} A minimal observable of state changes. * For more information, see the observable proposal: * https://github.com/tc39/proposal-observable * * observable/reactive库的互用性 * observable是一个mini的 可观察state的改变 * 在下面这个网址查看更多observable的信息 */ 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. * * mini的可观察订阅的方法 * observer是 任何对象均可以用做观察者,这个观察者应该有一个`next`方法 * subscription 一个有`unsubscribe`方法的对象.能够用作退订observable,防止进一步发出value值 * (我也不知道什么意思,外国人说话比较随意) */ 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 } } } // When a store is created, an "INIT" action is dispatched so that every // reducer returns their initial state. This effectively populates // the initial state tree. /** * 当建立一个store的时候,一个初始的action就被dispatch了,因此每一个reducer都会返回初始的state * 这个能够很高效的获得state树 */ dispatch({ type: ActionTypes.INIT }) return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable } }
源码解析请参考 https://segmentfault.com/a/11...react