createStore

概述

createStore 的作用和 redux 的 createStore 方法类似,它只是在其之外做了些事情。

源码位置

dva/packages/dva-core/src/createStore.js

解析

通过分析源码我们把整个代码分成如下几个部分,各部对应的源码在下方用注释表明。

源码

export default function({
  reducers,
  initialState,
  plugin,
  sagaMiddleware,
  promiseMiddleware,
  createOpts: { setupMiddlewares = returnSelf },
}) {
  // ------- 1. 获取并校验 extraEnhancers --------
  const extraEnhancers = plugin.get('extraEnhancers');
  invariant(
    isArray(extraEnhancers),
    `[app.start] extraEnhancers should be array, but got ${typeof extraEnhancers}`
  );

  // ------- 2. 生成 middlewares
  const extraMiddlewares = plugin.get('onAction');
  const middlewares = setupMiddlewares([
    promiseMiddleware,
    sagaMiddleware,
    ...flatten(extraMiddlewares),
  ]);

  let devtools = () => noop => noop;
  // -------- 忽略 dev 代码 ---------
  if (
    process.env.NODE_ENV !== 'production' &&
    window.__REDUX_DEVTOOLS_EXTENSION__
  ) {
    devtools = window.__REDUX_DEVTOOLS_EXTENSION__;
  }

  // -------- 3. 生成 enhancers ---------
  const enhancers = [
    applyMiddleware(...middlewares),
    ...extraEnhancers,
    devtools(window.__REDUX_DEVTOOLS_EXTENSION__OPTIONS),
  ];

  // --------- 4. 调用 redux.createStore --------
  return createStore(reducers, initialState, compose(...enhancers));
}

1. 获取并校验 extraEnhancers

通过 plugin 获取所有的 extraEnhancers 并且判断其类型是否为数组

2. 生成 middlewares

通过 setupMiddlewares 生成所有的 middlewares,setupMiddlewares 是在 dva() 源码里面传过去的,我把代码放在下面了,可以看到最终返回的 middewares 数组包含:routerMiddleware promiseMiddleware sagaMiddleware extraMiddlewares

提示

flatten 库是将一个多维数组展开为一维数组

const createOpts = {
  initialReducer: {
    routing,
  },
  setupMiddlewares(middlewares) {
    return [
      routerMiddleware(history),
      ...middlewares,
    ];
  },
  setupApp(app) {
    app._history = patchHistory(history);
  },
};
// ------- from dva/src/index.js

3. 生成 enhancers

enhancers 是 redux 里面的术语,用于扩展 createStore,这里生成的 enhancers 主要有三种:

  • 我们将之前生成的 middlewares 调用 applyMiddleware 生成 enhancers
  • 之前获取的 extraEnhancers
  • devtools 在 dev 环境下如果引入了 redux-devtools 会自动引入

4. 调用 redux.createStore

调用 createStore 生成 store 对象并返回