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 | dispatch({ |
dispatch函数
dispatching function 是一个用于触发 action 的函数,向effect 或 reducer派发action(派发action也就是调用某个函数), effect通过yield put向reducer派发action
action 是改变 State 的唯一途径,但是它只描述了一个行为,而 dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。
reducer
Reducer 的概念来自于是函数式编程,很多语言中都有 reduce API。如在 javascript 中:
1 | [{x:1},{y:2},{z:3}].reduce(function(prev, next){ |
在 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 | import key from 'keymaster'; |
Router
这里的路由通常指的是前端路由,由于我们的应用现在通常是单页应用,所以需要前端代码来控制路由逻辑,通过浏览器提供的 History API 可以监听浏览器url的变化,从而控制路由相关操作。
dva 实例提供了 router 方法来控制路由,使用的是react-router。
1 | import { Router, Route } from 'dva/router'; |
Route Components
在 dva 中,通常需要 connect Model的组件都是 Route Components,组织在/routes/目录下,而/components/目录下则是纯组件(Presentational Components)。
组件相关知识:
Generator 函数
Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。
call 和 put
dva 提供多个 effect 函数内部的处理函数,比较常用的是 call 和 put。
- call:执行异步函数
- put:发出一个 Action,类似于 dispatch
核心概念
- State:一个对象,保存整个应用状态
- View:React 组件构成的视图层
- Action:一个对象,描述事件
- connect 方法:一个函数,绑定 State 到 View
- dispatch 方法:一个函数,发送 Action 到 State
DVA解决了什么问题
1 通信:组件之间的通信
2 数据流: 数据和视图如何串联;路由和数据如何绑定;如何编写异步逻辑