一、dva解决了什么痛点?
1. 组件之间的通信:React组件对于父子,兄弟之间的通信,只能通过传参完成,对于大型应用,不太方便。
2. 数据流: 数据如何与视图串联起来?路由和数据如何绑定?如何编写异步逻辑等?
3.没有用dva之间的数据流方案比较复杂,要引入多个第三方的库:
路由:react-router
架构: redux
异步操作:redux-saga
引入dva后,把上面三个进行了工具库包进行包装,简化了api,让开发变得更容易。
二、dva数据流概念:
原理:数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch
发起一个 action,如果是同步行为会直接通过 Reducers
改变 State
,如果是异步行为(副作用)会先触发 Effects
然后流向 Reducers
最终改变 State
,所以在 dva 中,数据流向非常清晰简明,并且思路基本跟开源社区保持一致(也是来自于开源社区)。
- State:一个对象,保存整个应用状态
- View:React 组件构成的视图层
- Action:一个对象,描述事件
- connect 方法:一个函数,绑定 State 到 View
- dispatch 方法:一个函数,发送 Action 到 State
同步数据流:
异步数据流:
三、dva的model如何定义:
dva优势就是把React+Redux+Saga集成起来了,同时基于它做了最佳的实践沉淀,做了三件事,提升了代码体验:
-
把 store 及 saga 统一为一个
model
的概念, 写在一个 js 文件里 -
增加了一个 Subscriptions, 用于收集其他来源的 action, eg: 键盘操作
-
model 写法很简约, 类似于 DSL 或者 RoR, coding 快得飞起✈️
model如何定义:
namespace:
state: 数据结构变量的声明
reducers:纯函数集 (即通过action改变state),定义同步action动作
effects:异步函数集,定义异步action动作
subscriptions: 订阅函数集
例子:
app.model({
namespace: 'count',
state: {
record: 0,
current: 0,
},
reducers: {
add(state) {
const newCurrent = state.current + 1;
return { ...state,
record: newCurrent > state.record ? newCurrent : state.record,
current: newCurrent,
};
},
minus(state) {
return { ...state, current: state.current - 1};
},
},
effects: {
*add(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'minus' });
},
},
subscriptions: {
keyboardWatcher({ dispatch }) {
key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
},
},
});
四、model如何react组件绑定,即state和视图的串起来,通过connect.(也可以用@connect装饰符来弄)