Use umi with dva

>= umi@2起,dva的整合可以直接通过 umi-plugin-react 来配置。

特性

  • 按目录约定注册 model,无需手动 app.model
  • 文件名即 namespace,可以省去 model 导出的 namespace key
  • 无需手写 router.js,交给 umi 处理,支持 model 和 component 的按需加载
  • 内置 query-string 处理,无需再手动解码和编码
  • 内置 dva-loading 和 dva-immer,其中 dva-immer 需通过配置开启
  • 开箱即用,无需安装额外依赖,比如 dva、dva-loading、dva-immer、path-to-regexp、object-assign、react、react-dom 等

使用

用 yarn 安装依赖,

  1. $ yarn add umi-plugin-react

如果你用 npm,执行 npm install --save umi-plugin-react

然后在 .umirc.js 里配置插件:

  1. export default {
  2. plugins: [
  3. [
  4. 'umi-plugin-react',
  5. {
  6. dva: true,
  7. },
  8. ]
  9. ],
  10. };

推荐开启 dva-immer 以简化 reducer 编写,

  1. export default {
  2. plugins: [
  3. [
  4. 'umi-plugin-react',
  5. {
  6. dva: {
  7. immer: true
  8. }
  9. }
  10. ],
  11. ],
  12. };

model 注册

model 分两类,一是全局 model,二是页面 model。全局 model 存于 /src/models/ 目录,所有页面都可引用;页面 model 不能被其他页面所引用

规则如下:

  • src/models/**/*.js 为 global model
  • src/pages/**/models/**/*.js 为 page model
  • global model 全量载入,page model 在 production 时按需载入,在 development 时全量载入
  • page model 为 page js 所在路径下 models/**/*.js 的文件
  • page model 会向上查找,比如 page js 为 pages/a/b.js,他的 page model 为 pages/a/b/models/**/*.js + pages/a/models/**/*.js,依次类推
  • 约定 model.js 为单文件 model,解决只有一个 model 时不需要建 models 目录的问题,有 model.js 则不去找 models/**/*.js

举个例子,

  1. + src
  2. + models
  3. - g.js
  4. + pages
  5. + a
  6. + models
  7. - a.js
  8. - b.js
  9. + ss
  10. - s.js
  11. - page.js
  12. + c
  13. - model.js
  14. + d
  15. + models
  16. - d.js
  17. - page.js
  18. - page.js

如上目录:

  • global model 为 src/models/g.js
  • /a 的 page model 为 src/pages/a/models/{a,b,ss/s}.js
  • /c 的 page model 为 src/pages/c/model.js
  • /c/d 的 page model 为 src/pages/c/model.js, src/pages/c/d/models/d.js

配置及插件

之前在 src/dva.js 下进行配置的方式已 deprecated,下个大版本会移除支持。

src 目录下新建 app.js,内容如下:

  1. export const dva = {
  2. config: {
  3. onError(e) {
  4. e.preventDefault();
  5. console.error(e.message);
  6. },
  7. },
  8. plugins: [
  9. require('dva-logger')(),
  10. ],
  11. };

FAQ

url 变化了,但页面组件不刷新,是什么原因?

layouts/index.js 里如果用了 connect 传数据,需要用 umi/withRouter 高阶一下。

  1. import withRouter from 'umi/withRouter';
  2. export default withRouter(connect(mapStateToProps)(LayoutComponent));

如何访问到 store 或 dispatch 方法?

  1. window.g_app._store
  2. window.g_app._store.dispatch

如何禁用包括 component 和 models 的按需加载?

在 .umirc.js 里配置:

  1. export default {
  2. plugins: [
  3. [
  4. 'umi-plugin-react',
  5. {
  6. dva: {
  7. dynamicImport: undefined // 配置在dva里
  8. },
  9. dynamicImport: undefined // 或者直接写在react插件的根配置,写在这里也会被继承到上面的dva配置里
  10. }
  11. ],
  12. ],
  13. };

全局 layout 使用 connect 后路由切换后没有刷新?

需用 withRouter 包一下导出的 react 组件,注意顺序。

  1. import withRouter from 'umi/withRouter';
  2. export default withRouter(connect()(Layout));

参考