前言

这篇简单介绍一下dva

为什么要有dva

在使用react开发时,进行reactrouterredux的配置比较繁琐,而dva考虑到这个问题,而对它们进行了一层封装,从而让开发变得更加方便。

官方介绍:dva 是一个基于 reduxredux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-routerfetch,所以也可以理解为一个轻量级的应用框架。

使用方法

在index.tsx中创建dva应用,并且配置reduxrouter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import './style/index.css';
import dva from "dva";
import counterModel from "./models/counter"
import usersModel from "./models/user"
import { createBrowserHistory } from "history"
import routerConfig from "./router/index";


// 创建一个dva应用
const app = dva({
// 这个history会用于router和redux
history : createBrowserHistory()
});

// 使用model配置redux
// 要在启动之前定义model
app.model(counterModel);
app.model(usersModel);

// 使用router配置路由
// 配置一个函数,这个函数会在启动时运行
// 函数的返回结果会被渲染
app.router(routerConfig);

// 启动app
app.start("#root");

model中可以进行一些redux相关的配置,可以理解这里整合了redux的action、reducer、redux-saga 副作用处理等等东西,配置如下

  • namespace:命名空间,该属性是一个字符串,字符串的值,会被作为仓库中的属性保存
  • state:该模型的默认状态
  • reducers: 该属性配置为一个对象,对象中的每个方法就是一个reducer,dva约定,方法的名字,就是匹配的action类型
  • effects: 处理副作用,底层是使用redux-saga实现的,该属性配置为一个对象,对象中的每个方法均处理一个副作用,方法的名字,就是匹配的action类型。
    1. 函数的参数1:action
    2. 参数2:封装好的saga/effects对象
  • subscriptions:配置为一个对象,该对象中可以写任意数量任意名称的属性,每个属性是一个函数,这些函数会在模型加入到仓库中后立即运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// models/counter
export default {
namespace: "counter",
state: 0,
reducers: {
increase(state) {
return state + 1;
},
decrease(state) {
return state - 1;
},
add(state, { payload }) {
return state + payload;
}
},
effects: {
*asyncIncrease(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: "increase" })
},
*asyncDecrease(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: "decrease" })
}
},
subscriptions: {
onresize({ dispatch }) {
window.onresize = () => {
console.log("窗口尺寸变化了")
}
}
}
}

function delay(duration) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, duration);
})
}

然后是路由相关的配置,路由的话,dva没有做太多东西,基本和原生一致,但是你可以很方便的同步路由到redux,使用下面的方法即可

  • 在调用dva函数时,配置history对象
  • 使用ConnectedRouter提供路由上下文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// router/index
import React from 'react'
import Counter from "../component/Counter"
import App from "../component/App/App";
import Home from "../component/Home";
import { routerRedux, NavLink, Route, Switch } from "dva/router"

// routerRedux导出了connected-react-router库里的东西
// history就是在dva app配置中的history
export default function ({ history }) {
return (
<routerRedux.ConnectedRouter history={history}>
<App>
<div>
<ul>
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/counter">Counter</NavLink>
</li>
</ul>
<div>
<Switch>
<Route path="/counter" component={Counter} />
<Route path="/" component={Home} />
</Switch>
</div>
</div>
</App>
</routerRedux.ConnectedRouter>
)
}

效果大概是这样

image-20210207170227302

image-20210207170120477