这里有一个很常见的需求,我们需要在进入页面的时候,发起请求页面初始化数据。这里我们通过 dva model 的 subscriptions 实现。

src/models/hero.ts subscriptions

  1. import { Effect, Reducer, Subscription } from 'umi';
  2. export interface HeroModelType {
  3. namespace: 'hero';
  4. state: HeroModelState;
  5. effects: {
  6. query: Effect;
  7. };
  8. reducers: {
  9. save: Reducer<HeroModelState>;
  10. };
  11. + subscriptions: { setup: Subscription };
  12. }
  13. HeroModel 中增加 subscriptions
  14. subscriptions: {
  15. setup({ dispatch, history }) {
  16. return history.listen(({ pathname, query }) => {
  17. if (pathname === '/hero') {
  18. dispatch({
  19. type: 'fetch'
  20. })
  21. }
  22. });
  23. }
  24. },

这里需要注意的是,subscriptions 是一个全局的监听,就是说,当设定触发条件满足时,所有的 subscriptions 都会响应,所以我们在这里判断了路由为当前路由时,发起一个 effects 事件。


src/models/hero.ts effects

然后在 effects 里面,响应这个事件。

  1. effects: {
  2. *fetch({ type, payload }, { put, call, select }) {
  3. const data = [
  4. {
  5. ename: 105,
  6. cname: '廉颇',
  7. title: '正义爆轰',
  8. new_type: 0,
  9. hero_type: 3,
  10. skin_name: '正义爆轰|地狱岩魂',
  11. },
  12. {
  13. ename: 106,
  14. cname: '小乔',
  15. title: '恋之微风',
  16. new_type: 0,
  17. hero_type: 2,
  18. skin_name: '恋之微风|万圣前夜|天鹅之梦|纯白花嫁|缤纷独角兽',
  19. },
  20. ];
  21. yield put({
  22. type: 'save',
  23. payload: {
  24. heros: data,
  25. },
  26. });
  27. },
  28. },

这里的 *fetch 前面的 * 表示它是一个异步函数,你可以在里面使用 yield 进行等待操作(什么是 Effect ?)。这里的 put 方法和 dispatch 方法可以理解为同一个方法,只是在不同的地方,用不同的方法名表示而已。这里我们写了一个静态数据,然后又发起了一个叫做 save 的事件。

别忘了在类型定义里面增加属性定义哦

  1. export interface HeroModelType {
  2. namespace: 'hero';
  3. state: HeroModelState;
  4. effects: {
  5. query: Effect;
  6. fetch: Effect;
  7. };
  8. reducers: {
  9. save: Reducer<HeroModelState>;
  10. };
  11. subscriptions: { setup: Subscription };
  12. }

src/models/hero.js reducers

最终我们在 reducers 中响应了这个 save 事件,用于更新页面数据,触发页面更新。

  1. reducers: {
  2. save(state, action) {
  3. return { ...state, ...action.payload };
  4. },
  5. },

这里我们定义了一个比较通用的方法,在 effects 发起需要更新数据时,全部发起 save 事件。然后在 save 中只是简单的把 payload 解构出来,部分覆盖了页面的 state 。当然我们这次的 effect/fetch 里发起了更新一个叫做 heros 的对象,但是我们的页面 state 中没有。

  1. state:{
  2. name:''
  3. }

所以我们还要修改我们页面的state

  1. state: {
  2. name:'',
  3. heros: [],
  4. },

修改完,保存,修改页面,因为 heros 是一个对象。我们可以简单的将它转化成字符串

  1. <h2>This is {JSON.stringify(props.hero)}</h2>

监听路由事件 - 图1

这样我们就实现了,监听路由事件取得静态数据,修改页面 state ,触发页面重绘。

别忘了state的类型定义

  1. export interface HeroModelState {
  2. name: string;
  3. heros: [];
  4. }