0.Dva
Dva其实就是一个管理数据流的框架,学React的时候我们会发现各种组件之间传参,会通过状态上升,也就是props,上层调用下层,但是如果有好几层,就会使得这个数据传输过程十分繁琐,于是就有了Dva,类似于我们的一个数据中心管理。
1.文件位置
符合以下规则的文件会被认为是 model 文件,一个model文件其实就是一个dva数据站。
- src/models 下的文件 (推荐)
- src/pages 下,子目录中 models 目录下的文件
- src/pages 下,所有 model.ts 文件(不区分任何字母大小写)
2.Model结构
创建一个model文件,取名叫dva.ts,文件架构如下:
export default {
// 命名空间,唯一
namespace: "dva",
// 状态 - 数据位置
state: {},
// 调用服务端接口 - 数据来源
effects: {},
// 更新状态 - 修改数据
reducers: {},
}
这样我们就算是把model创建好了,你可以通过指令查看是否通过了成功被识别。
$ umi dva list model
创建成功,被加入到了model库中。
然后我们创建一个组件,并且让他们连接起来。
3.创建Ui组件并连接
我们在pages目录下创建一个组件文件dva.tsx
import React from 'react';
import {connect} from 'umi';
const Dva = () => {
return (
<div>
<h1>Dva的使用测试</h1>
</div>
);
};
export default connect(({dva})=>({dva}))(Dva);
主要是用了一个connect,connect是umi自带的函数,用于绑定数据到组件上。
4.完善Model
现在万事具备了,就差model中的数据了,但这也是比较复杂的一部分,我们拆开来说。
namespace 是该 model 的命名空间,同时也是全局 state 上的一个属性,只能是字符串,不支持使用 xx.xx 创建多层命名空间。
namespace: "dva",
state是状态,是数据对象本身,也可以理解为数据初始值,这个和React中的state如出一辙.
state: {
cityList: [],
}
effect用于处理异步操作,是相对这里面比较复杂的一个。它不能直接修改 state需要通过put调用reducers来更新state,由 action 触发,也可触发 action。它只能是 generator 函数,并且有 action 和 effects 两个参数。第二个参数 effects 包含 put、call 和 select 三个字段,put 用于触发 action,call 用于调用异步处理逻辑,select 先不讲,以后用到再说。
effects: {
//payload 获取组件中参数,例如表单提交获得到的数据
//callback 回调函数,例如提交成功后跳出一个提示框
//put 触发action
//call 访问外部方法,获取外部数据 call(方法,方法传参)
* queryCityList({payload, callback}, {put, call}) {
//获取tags数据,yield实现异步
const res = yield call(getCitys)
//调用reducers,更新state
yield put({
type: 'setCityList', // 类似于 redux 中 action 的 type
payload: res
})
}
},
类似于 redux 中的 reducer,它是一个纯函数,用于处理同步操作,是唯一可以修改 state 的地方,由 action 触发,它有 state 和 action 两个参数。
reducers: {
setCityList(state, action) {
return {...state, cityList: action.payload}
}
},
5.Ui组件获取数据
因为 export default connect(({dva}) => ({dva}))(Dva); 把数据都传到了Dva里面的props.dva,我们通过其中的dispach去发送action获取我们数据。这里的 type: ‘dva/queryCityList’ 其实就是调用了effect中的generator 函数。
import React from 'react';
import {connect} from 'umi';
import {Button} from 'antd';
const Dva = (props: any) => {
const {dispatch} = props;
const list = props.dva.cityList.list || [];
console.log(list)
const getData = () => {
//使用model,获取数据
dispatch({
type: 'dva/queryCityList',// model命名空间/调用的方法
payload: null
})
}
return (
<div>
<h1>Dva的使用测试</h1>
<Button onClick={getData}>获取列表数据</Button>
<table>
<tr><th>城市名</th><th>数量</th><th>城市类型</th></tr>
{
list.map((item, index) => {
return <tr key={index}>
<td>{item.name}</td>
<td>{item.value}</td>
<td>{item.type}</td>
</tr>
})
}
</table>
</div>
);
};
export default connect(({dva}) => ({dva}))(Dva);