1、connect
用来将model
、component
链接在一起。 component
里可以拿到model
中定义的数据, model
中也能接收到component
里的dispatch的action
2、action
action在model自身模型以外定义时需要加model的namespace前缀, 在model中定义不需要加
表示操作事件可以是同步,也可以是异步。是view
视图发出的通知,表示state
应该要发生变化
3、dispatch
view
发出action
的唯一方法。通过type
属性指定对应的action
类型,这个类型名在reducers(effects)
会一一对应, 从而知道应该调用哪一个reducers(effects
),除了type
以外,其它对象中的参数可以随意定义
,都可以在对应的reducers(effects)
中获取,从而实现消息传递,将最新的数据传递过去更新model
的数据(state)
4、reducer
唯一可以更新state的地方
接收到action
后,必须给出一个新的state
,这样view
才会变化,这种state
的计算过程就叫reducer
。
5、effects
在
effects
中,Generator
函数通过yeild
命令将异步操作同步化,无论是yeild
、async
目的只有一个,让异步编程跟同步一样,从而能够很好的控制执行流程
用来处理异步任务, 这是基于Redux-saga 中文文档
6、*functionName(action, { call, select, put... })
表示一个worker Saga,监听所有的functionName action
,并且触发一个API调用以获取服务器的数据。当每个functionName action
被发起时调用call
和put
都是Redux-saga 的effects
, call表示调用异步函数, put表示dispatch action, select则可以用来访问其他model,格式:*(action, effects) => void
其他的还有take
、fork
、cancle
等
7、subScriptions
用于订阅一个数据源,然后按需dispatch action
。格式为:({dispatch, history})=> unsubscribe
subscriptions: {
setup(( dispatch, history )){
history.listen(({ pathname, query }) => {
if(pathToRegexp(`/y/monthCard/list`).test(pathname)) {
dispatch({
type:`query`
})
}
})
}
}
代码分析:当用户进入‘/y/monthCard/list’页面时,触发action functionName
加载数据
如果url规则比较复杂,‘/users/:userId/search’, name匹配和userId的获取都会比较麻烦。这时推荐用path-to-regexp简化这部分逻辑
举例:
一、index.ts文件
import React, { createRef, ChangeEvent } from 'react';
import { connect, Dispatch, AnyAction } from 'umi';
import { StateType } from './model';
interface ClientPropertyProps {
dispatch: Dispatch;
clientProperty: StateType;
loading: boolean;
}
class ClientProperty extends React.Component <ClientPropertyProps>{
state = {
configKey: 'consumerFields'
}
cmponentDidMount() {
this.fetchClientProperty({
type: this.state.configKey
})
}
fetchClientProperty(payload = {}) {//this.props可以调取connect中所有model的方法和属性
this.props.dispatch({type: 'clientProperty/getClientProperties', payload});
}
}
export default connect(({
clientProperty,
loading
}: {//这一步是为了加类型约束
clientProperty: StateType;// StateTypee是接口
loading: {
effects: {
[key: string]: boolean;
};
};
}) => ({
clientProperty,
loading: loading.effects['clientProperty/getClientProperties'],
}))(ClientProperty);
二、model.ts文件
import * as settingService from '@/services/setting';
export interface StateType {
clientProperties: any[]; //接口
}
const Model = {
namespace: 'clientProperty',
state: {
clientProperties: [],
},
subscriptions: {
setup({dispatch, history}){ }
},
effects: {
*getClientProperties({ payload }, { call, put, select }) {
let clientProperties = yield select((state: any) => {
console.log(state) //可以输出应用层所有的model以及在model中定义的state值
return [...state.clientProperty.clientProperties]);
}
const { data, response } = yield call(settingService.getClientProperties, payload);
if (!data.value) {
data.key = payload.type
}
if (response && response.ok === true) {
yield put({
type: 'updateClientProperties',
payload: generateClientProperties(data && data.value || [])
});
}
},
},
reducers: {
updateClientProperties(state, { payload }) {
return {
...state,
clientProperties: payload
};
}
}
}
export default Model;
三、setting.ts文件
import request from '@/utils/request';
export async function getClientProperties(params: {type: string}): Promise<any> {
const key = params && params.type || 'consumerFields'
return request.v1.get(`/app/config/${key}`);
}
网友评论