这里有一个很常见的需求,我们需要在进入页面的时候,发起请求页面初始化数据。这里我们通过 dva model 的 subscriptions 实现。
src/models/hero.ts subscriptions
import { Effect, Reducer, Subscription } from 'umi';
export interface HeroModelType {
namespace: 'hero';
state: HeroModelState;
effects: {
query: Effect;
};
reducers: {
save: Reducer<HeroModelState>;
};
+ subscriptions: { setup: Subscription };
}
HeroModel 中增加 subscriptions
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname, query }) => {
if (pathname === '/hero') {
dispatch({
type: 'fetch'
})
}
});
}
},
这里需要注意的是,subscriptions 是一个全局的监听,就是说,当设定触发条件满足时,所有的 subscriptions 都会响应,所以我们在这里判断了路由为当前路由时,发起一个 effects 事件。
src/models/hero.ts effects
然后在 effects 里面,响应这个事件。
effects: {
*fetch({ type, payload }, { put, call, select }) {
const data = [
{
ename: 105,
cname: '廉颇',
title: '正义爆轰',
new_type: 0,
hero_type: 3,
skin_name: '正义爆轰|地狱岩魂',
},
{
ename: 106,
cname: '小乔',
title: '恋之微风',
new_type: 0,
hero_type: 2,
skin_name: '恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽',
},
];
yield put({
type: 'save',
payload: {
heros: data,
},
});
},
},
这里的 *fetch
前面的 *
表示它是一个异步函数,你可以在里面使用 yield 进行等待操作(什么是 Effect ?)。这里的 put 方法和 dispatch 方法可以理解为同一个方法,只是在不同的地方,用不同的方法名表示而已。这里我们写了一个静态数据,然后又发起了一个叫做 save 的事件。
别忘了在类型定义里面增加属性定义哦
export interface HeroModelType {
namespace: 'hero';
state: HeroModelState;
effects: {
query: Effect;
fetch: Effect;
};
reducers: {
save: Reducer<HeroModelState>;
};
subscriptions: { setup: Subscription };
}
src/models/hero.js reducers
最终我们在 reducers 中响应了这个 save 事件,用于更新页面数据,触发页面更新。
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
这里我们定义了一个比较通用的方法,在 effects 发起需要更新数据时,全部发起 save 事件。然后在 save 中只是简单的把 payload 解构出来,部分覆盖了页面的 state 。当然我们这次的 effect/fetch 里发起了更新一个叫做 heros 的对象,但是我们的页面 state 中没有。
state:{
name:''
}
所以我们还要修改我们页面的state
state: {
name:'',
heros: [],
},
修改完,保存,修改页面,因为 heros 是一个对象。我们可以简单的将它转化成字符串
<h2>This is {JSON.stringify(props.hero)}</h2>
这样我们就实现了,监听路由事件取得静态数据,修改页面 state ,触发页面重绘。
别忘了state的类型定义
export interface HeroModelState {
name: string;
heros: [];
}