1 model的分类
model 分两类,一是全局 model,二是页面 model。全局 model 存于
/src/models/
目录,所有页面都可引用;页面 model 不能被其他页面所引用。
但是又发现了 dva 官方文档这样写
注意:如果当前应用中加载了不止一个model,在其中一个的effect里面做select操作,是可以获取另外一个中的state的。
所以,借助这个特点,我们就不必非要把model按照视图的结构进行组织,可以适当按照业务分类,把一些数据存在对应业务的model中,分别通过不同的effect去更新,在获取的地方再去组合,这样可以使得model拥有更好的复用性。
经过测试发现确实是这样,
const current = yield select(state => state.formAndstepForm.current);
yield put({
type: "formAndbasicForm/clearTest",
});
即如果model被加载,不仅可以通过state来访问到其他页面的state,而且可以使用其他页面的 reducer、effect 来操作model中的state数据。
2 call put select 的使用
- call
经常用来发送异步http请求
const reponse = yield call(queryList, payload);
这里,queryList 是services 文件中的一个请求数据的异步方法(用async修饰的函数),其中 payload 会自动作为 queryList 的参数传入,因此 queryList 可以这样写:
export async function queryList(params: Pick<queryList, 'fetchParams'>) {
const url = '';
return request(`${url}`, {
params,
});
}
- put
用来实现其他 action(包括异步action) 的传递,与dispatch 的作用类似,
dispatch({
type: "save",
payload: {
/*数据*/
};
});
//等价于
yield put({
type: "save",
payload: {
/*数据*/
};
})
注意:yield put 返回的数据是 undefined
- select
可以用来去state中的其他属性值。antd pro 中取得state对象属性的方法:
const num = yield select(state => state.nameSpace1.num);
注意:要在 state 后边加上本 model 的 nameSpace 名称才能访问到其中state 的值。
3 触发effect 和 reducer 的方法
- 触发 effect 的方法
(1)本 model 下的其他effect下
yield put({
type: "asyncSameModel",
});
(2)在其他model下的effect下
yield put({
type: "nameSpace1/asyncSameModel",
});
(3)在其他 非model 下
const { dispatch } = this.props;
dispatch({
type: "nameSpace1/asyncSameModel",
});
- 触发reducer 的方法
类似 effect 的触发方法,
(1)在本 model 的effect下
yield put({
type: "clearTest",
});
注意:由于调用方式与 effect 相同,所以应为每个 reducer 和 effect 方法做命名区分,否则程序把 reducer 和 effect 都给执行了。
(2)在 其他model 的 effect 下,与 effect 的调用方式类似:
yield put({
type: "nameSpace1/clearTest",
});
(3)在非 model 的文件中触发
const { dispatch } = this.props;
dispatch({
type: "nameSpace1/clearTest",
});
4 dva 的 connect 方法
@connect 是 connect 的语法糖,必须放在组件定义之前,它需要提供一个函数作为参数。函数的参数是本页面所用到的 models 的集合(以model的 nameSpace 作为key的对象),函数需要返回的该组件需要的具体某个 models 下的某些数据。例如:
/* eslint react/no-multi-comp:0 */
@connect(
({
listAndtableList,
loading,
}: {
listAndtableList: StateType;
loading: {
effects: {
[key: string]: boolean;
};
};
}) => ({
listAndtableList,
loading: loading.effects['listAndtableList/fetch'],
}),
)
上述是将 listAndtableList 和 loading 的 effects 对象下 listAndtableList/fetch 组合成为返回的对象。
总之,@connect 扮演了 redux 中的 mapStateToProps 的作用。
注意:对于 mapDispatchToProps 不作为第二个参数传入,dva 直接给组件提供了 dispatch 的属性,可以直接通过 CC 的 this.props.dispatch 和 FC 的props.dispatch 来分发 action。即与 redux 区别主要在于 将事件的处理和dispatch逻辑 放在了组件下。