Model

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

  1. app.model({
  2. namespace: 'todo',
  3. state: [],
  4. reducers: {
  5. add(state, { payload: todo }) {
  6. // 保存数据到 state
  7. return [...state, todo];
  8. },
  9. },
  10. effects: {
  11. *save({ payload: todo }, { put, call }) {
  12. // 调用 saveTodoToServer,成功后触发 `add` action 保存到 state
  13. yield call(saveTodoToServer, todo);
  14. yield put({ type: 'add', payload: todo });
  15. },
  16. },
  17. subscriptions: {
  18. setup({ history, dispatch }) {
  19. // 监听 history 变化,当进入 `/` 时触发 `load` action
  20. return history.listen(({ pathname }) => {
  21. if (pathname === '/') {
  22. dispatch({ type: 'load' });
  23. }
  24. });
  25. },
  26. },
  27. });

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 类型有:

subscriptions

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

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

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