转载   原文 https://blog.csdn.net/zhangrui_web/article/details/79651448

API

输出文件

dva

默认输出文件。

dva/router

默认输出 react-router 接口, react-router-redux 的接口通过属性 routerRedux 输出。

比如:

import { Router, Route, routerRedux } from 'dva/router';

dva/fetch

异步请求库,输出 isomorphic-fetch 的接口。不和 dva 强绑定,可以选择任意的请求库。

dva/saga

输出 redux-saga 的接口,主要用于用例的编写。(用例中需要用到 effects)

dva/dynamic

解决组件动态加载问题的 util 方法。

比如:

import dynamic from 'dva/dynamic'; const UserPageComponent = dynamic({ app, models: () => [ import('./models/users'), ], component: () => import('./routes/UserPage'), });

opts 包含:

  • app: dva 实例,加载 models 时需要
  • models: 返回 Promise 数组的函数,Promise 返回 dva model
  • component:返回 Promise 的函数,Promise 返回 React Component

dva API

app = dva(opts)

创建应用,返回 dva 实例。(注:dva 支持多实例)

opts 包含:

  • history:指定给路由用的 history,默认是 hashHistory
  • initialState:指定初始数据,优先级高于 model 中的 state,默认是 {}

如果要配置 history 为 browserHistory,可以这样:

import createHistory from 'history/createBrowserHistory'; const app = dva({ history: createHistory(), });

另外,出于易用性的考虑,opts 里也可以配所有的 hooks ,下面包含全部的可配属性:

const app = dva({history,initialState,onError,onAction,onStateChange,onReducer,onEffect,onHmr,extraReducers,extraEnhancers,
});

app.use(hooks)

配置 hooks 或者注册插件。(插件最终返回的是 hooks )

比如注册 dva-loading 插件的例子:

import createLoading from 'dva-loading'; ... app.use(createLoading(opts));

hooks 包含:

onError((err, dispatch) => {})

effect 执行错误或 subscription 通过 done 主动抛错时触发,可用于管理全局出错状态。

注意:subscription 并没有加 try...catch,所以有错误时需通过第二个参数 done 主动抛错。例子:

app.model({subscriptions: {setup({ dispatch }, done) {done(e); }, }, });

如果我们用 antd,那么最简单的全局错误处理通常会这么做:

import { message } from 'antd'; const app = dva({ onError(e) { message.error(e.message, /* duration */3); }, });

onAction(fn | fn[])

在 action 被 dispatch 时触发,用于注册 redux 中间件。支持函数或函数数组格式。

例如我们要通过 redux-logger 打印日志:

import createLogger from 'redux-logger'; const app = dva({ onAction: createLogger(opts), });

onStateChange(fn)

state 改变时触发,可用于同步 state 到 localStorage,服务器端等。

onReducer(fn)

封装 reducer 执行。比如借助 redux-undo 实现 redo/undo :

import undoable from 'redux-undo'; const app = dva({ onReducer: reducer => { return (state, action) => { const undoOpts = {}; const newState = undoable(reducer, undoOpts)(state, action); // 由于 dva 同步了 routing 数据,所以需要把这部分还原 return { ...newState, routing: newState.present.routing }; }, }, });

详见 examples/count-undo 。

onEffect(fn)

封装 effect 执行。比如 dva-loading 基于此实现了自动处理 loading 状态。

onHmr(fn)

热替换相关,目前用于 babel-plugin-dva-hmr 。

extraReducers

指定额外的 reducer,比如 redux-form 需要指定额外的 form reducer:

import { reducer as formReducer } from 'redux-form' const app = dva({ extraReducers: { form: formReducer, }, });

extraEnhancers

指定额外的 StoreEnhancer ,比如结合 redux-persist 的使用:

import { persistStore, autoRehydrate } from 'redux-persist'; const app = dva({ extraEnhancers: [autoRehydrate()], }); persistStore(app._store);

app.model(model)

注册 model,详见 #Model 部分。

app.unmodel(namespace)

取消 model 注册,清理 reducers, effects 和 subscriptions。subscription 如果没有返回 unlisten 函数,使用 app.unmodel 会给予警告⚠️。

app.router(({ history, app }) => RouterConfig)

注册路由表。

通常是这样的:

import { Router, Route } from 'dva/router'; app.router(({ history }) => { return ( <Router history={history}> <Route path="/" component={App} /> <Router> ); });

推荐把路由信息抽成一个单独的文件,这样结合 babel-plugin-dva-hmr 可实现路由和组件的热加载,比如:

app.router(require('./router'));

而有些场景可能不使用路由,比如多页应用,所以也可以传入返回 JSX 元素的函数。比如:

app.router(() => <App />);

app.start(selector?)

启动应用。selector 可选,如果没有 selector 参数,会返回一个返回 JSX 元素的函数。

app.start('#root');

那么什么时候不加 selector?常见场景有测试、node 端、react-native 和 i18n 国际化支持。

比如通过 react-intl 支持国际化的例子:

import { IntlProvider } from 'react-intl'; ... const App = app.start(); ReactDOM.render(<IntlProvider><App /></IntlProvider>, htmlElement);

Model

model 是 dva 中最重要的概念。以下是典型的例子:

app.model({namespace: 'todo', state: [], reducers: { add(state, { payload: todo }) { // 保存数据到 state return [...state, todo]; }, }, effects: { *save({ payload: todo }, { put, call }) { // 调用 saveTodoToServer,成功后触发 `add` action 保存到 state yield call(saveTodoToServer, todo); yield put({ type: 'add', payload: todo }); }, }, subscriptions: { setup({ history, dispatch }) { // 监听 history 变化,当进入 `/` 时触发 `load` action return history.listen(({ pathname }) => { if (pathname === '/') { dispatch({ type: 'load' }); } }); }, }, });

model 包含 5 个属性:

namespace

model 的命名空间,同时也是他在全局 state 上的属性,只能用字符串,不支持通过 . 的方式创建多层命名空间。

state

初始值,优先级低于传给 dva() 的 opts.initialState

比如:

  1. const app = dva({
  2. initialState: { count: 1 },
  3. });
  4. app.model({
  5. namespace: 'count',
  6. state: 0,
  7. });

此时,在 app.start() 后 state.count 为 1 。

reducers

以 key/value 格式定义 reducer。用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。

格式为 (state, action) => newState 或 [(state, action) => newState, enhancer]

详见: https://github.com/dvajs/dva/blob/master/packages/dva-core/test/reducers-test.js

effects

以 key/value 格式定义 effect。用于处理异步操作和业务逻辑,不直接修改 state。由 action 触发,可以触发 action,可以和服务器交互,可以获取全局 state 的数据等等。

格式为 *(action, effects) => void 或 [*(action, effects) => void, { type }]

type 类型有:

  • takeEvery
  • takeLatest
  • throttle
  • watcher

详见:https://github.com/dvajs/dva/blob/master/packages/dva-core/test/effects-test.js

subscriptions

以 key/value 格式定义 subscription。subscription 是订阅,用于订阅一个数据源,然后根据需要 dispatch 相应的 action。在 app.start() 时被执行,数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。

格式为 ({ dispatch, history }, done) => unlistenFunction

注意:如果要使用 app.unmodel(),subscription 必须返回 unlisten 方法,用于取消数据订阅。

转载于:https://www.cnblogs.com/Chasel-Chen/p/9550212.html

dva源码解析(三)相关推荐

  1. Disruptor源码解析三 RingBuffer解析

    目录 系列索引 前言 主要内容 RingBuffer的要点 源码解析 系列索引 Disruptor源码解析一 Disruptor高性能之道 Disruptor源码解析二 Sequence相关类解析 D ...

  2. OkHttp3源码解析(三)——连接池复用

    OKHttp3源码解析系列 OkHttp3源码解析(一)之请求流程 OkHttp3源码解析(二)--拦截器链和缓存策略 本文基于OkHttp3的3.11.0版本 implementation 'com ...

  3. ReactiveSwift源码解析(三) Signal代码的基本实现

    上篇博客我们详细的聊了ReactiveSwift源码中的Bag容器,详情请参见<ReactiveSwift源码解析之Bag容器>.本篇博客我们就来聊一下信号量,也就是Signal的的几种状 ...

  4. 并发编程与源码解析 (三)

    并发编程 (三) 1 Fork/Join分解合并框架 1.1 什么是fork/join ​ Fork/Join框架是JDK1.7提供的一个用于并行执行任务的框架,开发者可以在不去了解如Thread.R ...

  5. 前端入门之(vuex源码解析三)

    上两节前端入门之(vuex源码解析二)我们把vuex的源码大概的撸了一遍,还剩下(插件.getters跟module),我们继续哈~ 插件童鞋们可以去看看vuex在各个浏览器的状态显示插件,小伙伴可以 ...

  6. 拆轮子-RxDownload2源码解析(三)

    本文为博主原创文章,未经允许不得转载 造轮子者:Season_zlc 轮子用法请戳作者链接 ↑ 前言 本文主要讲述 RxDownload2 的多线程断点下载技术. 断点下载技术前提 服务器必须支持按 ...

  7. Tomcat源码解析三:tomcat的启动过程

    Tomcat组件生命周期管理 在Tomcat总体结构 (Tomcat源代码解析之二)中,我们列出了Tomcat中Server,Service,Connector,Engine,Host,Context ...

  8. 【Vue.js源码解析 三】-- 模板编译和组件化

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 模板编译 模板编译的主要目的是将模板 (template) 转换为渲染函数 (render) <div> ...

  9. Cesium源码解析三(metadata元数据拓展中行列号的分块规则解析)

    目录 1.前言 2.layer.json中available参数意义 3.EPSG:4626切片及terrain分块原理 4.Cesium的terrain分块规则 5.自定义terrain分块规则 6 ...

  10. AFNetworking2.0源码解析三

    本篇说说安全相关的AFSecurityPolicy模块,AFSecurityPolicy用于验证HTTPS请求的证书,先来看看HTTPS的原理和证书相关的几个问题. HTTPS HTTPS连接建立过程 ...

最新文章

  1. CodeChef--EQUAKE
  2. 【PAT (Advanced Level) Practice】1120 Friend Numbers (20 分)
  3. 网络编程学习方法和图书推荐
  4. 如何在ubuntu下安装detectron2_Anaconda中安装Cascade RCNN(Detectron)的若干问题
  5. python环境变量的配置 alias_vim-python环境配置
  6. Node.js构建可扩展的Web应用1
  7. linux 无线网卡连接网络连接不上去,【已解决】Ubuntu 10.04 无线网卡 无法连接
  8. 微信小程序---实现输入手机验证码功能
  9. win10 mysql 远程访问_win10 docker部署mysql并启动远程连接
  10. 第一批做移动开发的程序员,现在怎么样了?
  11. S3C6410和S5PV210的启动模式介绍
  12. No package ‘dconf‘ found
  13. 归并排序JAVA代码详解
  14. 国内android应用商城中程序隐私泄露分析,Android应用程序隐私数据泄露检测
  15. Appium Doctor iOS Could not detect Mac OS X Version from sw_vers output: '10.12 '解决方法
  16. Python处理文档
  17. 另眼看待王老吉 弱品类市场需要强场景突破
  18. 用WINPE安装WINXP原版纯净版ISO镜像的方法
  19. 2021-10-28 JAVA实验三学习总结
  20. 计算机主机风扇声音大的原因,台式电脑风扇响声大的原因和修复方法

热门文章

  1. 【C#】获取程序中Properties下的AssemblyInfo.cs下的信息
  2. 2018-2019赛季多校联合新生训练赛第六场补题与题解(中石油)
  3. 【ae】文字3D:动画3D:3D摄像机
  4. 可以免费使用的CDN加速你的网站
  5. 关于websphere的ibm-web-ext.xmi文件,该如何处理
  6. Microsoft Edge打开后会打开360导航页的解决方法
  7. rust木炭有用吗_Rust 2020 调查报告出炉,95%的开发者吐槽Rust难学
  8. NLP自然语言处理学习笔记(二)Word2Vec
  9. 基于宝塔面板的ZFaka(发卡程序)一键脚本
  10. 将一个数分解为质因数的乘积