Genius Lab.

Dva

Word count: 1.5kReading time: 5 min
2020/06/28 Share

DVA

参考文档:https://github.com/dvajs/dva-knowledgemap#javascript-%E8%AF%AD%E8%A8%80

如何触发数据改变: 1 用户交互行为 2浏览器行为(路由跳转)

当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State

如何使用effects:

在同步方法中通过dispatch方法派发action调用 type: effects函数名称

action是一个对象,payload也是一个对象

Model

Model是一个对象

相当于redux的store

Model 对象的属性

  • namespace: 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成
  • state: 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出
  • reducers: Action 处理器,处理同步动作,用来算出最新的 State
  • effects:Action 处理器,处理异步动作

state

state表示Model的状态数据

state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。

Action { }

action是一个普通js对象,它是改变state的唯一途径.

通过dispatch函数调用一个action

action 必须带有 type 属性指明具体的行为,其它字段可以自定义,如果要发起一个 action 需要使用 dispatch 函数;需要注意的是 dispatch 是在组件 connect Models以后,通过 props 传入的。

1
2
3
dispatch({
type: 'add',
});

dispatch函数

dispatching function 是一个用于触发 action 的函数,向effect 或 reducer派发action(派发action也就是调用某个函数), effect通过yield put向reducer派发action

action 是改变 State 的唯一途径,但是它只描述了一个行为,而 dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。

reducer

Reducer 的概念来自于是函数式编程,很多语言中都有 reduce API。如在 javascript 中:

1
2
3
4
[{x:1},{y:2},{z:3}].reduce(function(prev, next){
return Object.assign(prev, next);
})
//return {x:1, y:2, z:3}

在 dva 中,reducers 聚合积累的结果是当前 model 的 state 对象。通过 actions 中传入的值,与当前 reducers 中的值进行运算获得新的值(也就是新的 state)。需要注意的是 Reducer 必须是纯函数,所以同样的输入必然得到同样的输出,它们不应该产生任何副作用。并且,每一次的计算都应该使用immutable data,这种特性简单理解就是每次操作都是返回一个全新的数据(独立,纯净),所以热重载和时间旅行这些功能才能够使用。

Effect

Effect 被称为副作用,之所以叫副作用是因为它使得我们的函数变得不纯,同样的输入不一定获得同样的输出。

dva 为了控制副作用的操作,底层引入了redux-sagas做异步流程控制,由于采用了generator的相关概念,所以将异步转成同步写法,从而将effects转为纯函数。

effect里写generate函数

yield put(action) === yield put({type, payload})

数据从effect流向reducers

同步方法通过dispatch派发action.异步方法通过yield put派发action

也就是说把数据从effect推给reducer,使用yield put方法

*getList(action, effects) {} 相当于 *getList({payload}, {put, call, select}) { }

getList也是一个函数,一旦触发effect就会往reducer 中传数据

put

用于触发 action 。

1
yield put({ type: 'todos/add', payload: 'Learn Dva' });

call

用于调用异步逻辑,支持 promise 。

1
const result = yield call(fetch, '/todos');

select

用于从 state(全部的modal) 里获取数据。

1
const todos = yield select(state => state.todos);

Subscription

Subscriptions 是一种从 获取数据的方法,它来自于 elm。

Subscription 语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。

也可以理解为监听以上这些行为

1
2
3
4
5
6
7
8
9
10
import key from 'keymaster';
...
app.model({
namespace: 'count',
subscriptions: {
keyEvent({dispatch}) {
key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
},
}
});

Router

这里的路由通常指的是前端路由,由于我们的应用现在通常是单页应用,所以需要前端代码来控制路由逻辑,通过浏览器提供的 History API 可以监听浏览器url的变化,从而控制路由相关操作。

dva 实例提供了 router 方法来控制路由,使用的是react-router

1
2
3
4
5
6
import { Router, Route } from 'dva/router';
app.router(({history}) =>
<Router history={history}>
<Route path="/" component={HomePage} />
</Router>
);

Route Components

在 dva 中,通常需要 connect Model的组件都是 Route Components,组织在/routes/目录下,而/components/目录下则是纯组件(Presentational Components)。

组件相关知识:

https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/04-%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%B3%95.md

Generator 函数

Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。

call 和 put

dva 提供多个 effect 函数内部的处理函数,比较常用的是 callput

  • call:执行异步函数
  • put:发出一个 Action,类似于 dispatch

核心概念

  • State:一个对象,保存整个应用状态
  • View:React 组件构成的视图层
  • Action:一个对象,描述事件
  • connect 方法:一个函数,绑定 State 到 View
  • dispatch 方法:一个函数,发送 Action 到 State

DVA解决了什么问题

1 通信:组件之间的通信

2 数据流: 数据和视图如何串联;路由和数据如何绑定;如何编写异步逻辑

CATALOG
  1. 1. DVA
    1. 1.1. Model
      1. 1.1.1. Model 对象的属性
      2. 1.1.2. state
      3. 1.1.3. Action { }
      4. 1.1.4. dispatch函数
      5. 1.1.5. reducer
      6. 1.1.6. Effect
        1. 1.1.6.1. put
        2. 1.1.6.2. call
        3. 1.1.6.3. select
      7. 1.1.7. Subscription
      8. 1.1.8. Router
      9. 1.1.9. Route Components
    2. 1.2. Generator 函数
    3. 1.3. call 和 put
    4. 1.4. 核心概念
    5. 1.5. DVA解决了什么问题