首先呢,umi中只要通過connect
后就會自動注入dispatch
到props
中奢赂,3.0中提供ConnectRC
還方便了些陪白,在2.0使用類組件的時候,總是要顯示的聲明在接口里膳灶,或者去繼承一些東西咱士。
可仍然會寫出這樣的代碼
const { dispatch } = this.props;
這個函數(shù)在每一次注入的時候不都是一樣的嘛,由于我的路由配置都會通過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
統(tǒng)一管理,盡管默認是文件的名字
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);
通常觸發(fā)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';
}