首先呢,umi中只要通过connect
后就会自动注入dispatch
到props
中,3.0中提供ConnectRC
还方便了些,在2.0使用类组件的时候,总是要显示的声明在接口里,或者去继承一些东西。
可仍然会写出这样的代码
const { dispatch } = this.props;
这个函数在每一次注入的时候不都是一样的嘛,由于我的路由配置都会通过wrappers
设置公告组件
于是乎
window.umiDispatch = props.dispatch;
declare global {
interface Window {
umiDispatch: Dispatch;
}
}
其次呢,dva
提供的Model
并不灵活,不宜与扩展,比如一点
export default {
state: {
name,
},
reducers: {
save(state) {
state.name = payload.name;
},
},
state
和save
里的state是一个类型的,不用重复的写...
所以我自己定义了一个
import { SubscriptionsMapObject, EffectsCommandMap } from 'dva';
interface NModel<S> {
namespace: string;
state?: S;
reducers?: {
[key: string]: (state: S, action: any) => void;
};
effects?: {
[key: string]: (action: any, effects: EffectsCommandMap) => void;
};
subscriptions?: SubscriptionsMapObject;
}
将namespce
统一管理,尽管默认是文件的名字
namespace NModel {
export enum ENames {
MDTest = 'MDTest',
MDNotes = 'MDNotes',
}
}
一个model文件是这样的
import NModel from '@/common/type/NModel';
export namespace NMDTest {
export interface IState {
name: string;
}
}
export default {
namespace: NModel.ENames.MDTest,
state: {
name,
},
effects: {
*query() {
},
},
reducers: {
save(state) {
},
},
} as NModel<NMDTest.IState>;
为了方便connect
注入属性的时候也能得到提示,所有的state
声明也放入NModule
中管理
export interface IState {
[ENames.MDTest]: NMDTest.IState;
[ENames.MDNotes]: NMDNotes.IState;
}
就可以这样
export default connect(({ MDTest:{name} }: NModel.IState) => ({
name,
}))(TestHook);
通常触发dispatch
是这样的
dispatch({
type: 'products/getProducts',
payload: {
name:"oop"
},
});
这个type
属性涉及到的命名空间、方法名、传参是要靠硬记吗?总之我看了很多文章没找到什么好的方法,侵入性比较大,如果解决一个问题需要引入一个新的模式或概念,就要好好权衡一下值不值。
首先在NModel
文件中加入IAction
和dispatch
export class IAction<P = any> {
type: string;
namespace: string;
payload: P;
constructor(payload: P) {
this.payload = payload;
}
}
export function dispatch(action: NModel.IAction) {
window.umiDispatch({
type: `${action.namespace}/${action.type}`,
payload: action.payload,
});
}
属性默认就是public
的
那么在model文件中
export namespace NMDTest {
export interface IState {
name: string;
}
class Action<P> extends NModel.IAction<P> {
namespace = NModel.ENames.MDTest;
}
export class AEQuery extends Action<{ name: string }> {
type = 'query';
}
export class ARSave extends Action<{ name: string; age: number }> {
type = 'save';
}
}
export default {
effects: {
*query({ payload }: NMDTest.AEQuery, { put }) {
},
},
reducers: {
save(state, { payload }: NMDTest.ARSave) {
state.name = payload.name;
},
},
} as NModel<NMDTest.IState>;
使用的时候
NModel.dispatch(new NMDTest.ARSave({ name: 'oop', age: 12 }));
需要不断的加入模板代码是
export class AEQuery extends Action<{ name: string }> {
type = 'query';
}
网友评论