umi 之 model

506 阅读3分钟

model里其实就是一个对象,我们把这个对象导出

model.js

export default {
  namespace: 'test',
  state: {
    name:'lily'
  },
  effects: {
    *getList({ payload }, { call, put }) {
      const res = yield call(getList, payload);
      yield put({
        type: 'saveList',
        payload: res,
      });
    },
  },
  reducers: {
    saveList(state, action) {
     //必须return 否则会报错
      return { ...state, age:18,...action.payload };
    },
  },
  
};

model 包含 5 个属性:

namespace命名空间,相当于给model取个名字,但是各个model的namespce是不能重复的

state 数据仓库,就是存数据的地方,model里的数据都是存放在这里的

effects:简单来说我们的异步请求就写在这里

reducers:把数据存到仓库(存到state)里的唯一方法,我们修改state里的数据不能直接像this.name='liu'这样去修改,而必须通过调用reducers里的方法

subscriptions:订阅,在这里我的理解就是监听页面的,比如监听到进入了某某页面就让它执行相关代码之类的

model的结构就是这个样子,但是怎么把model和我们写的组件关联起来呢,只需要用到connect就可以啦。

index.js文件里的内容如下

import React from 'react';
import { connect } from 'umi'
class Index extends React.Component {
  render() {
    return (
      <div>
        <div className='box'>
        </div>
      </div>
    );
  }
}

//通过connect把model和我们写的Index关联起来,test是model的命名空间
const mapStateToProps = (state) => 
//必须返回一个对象
({
  ...state.test,
  ...state.test2,
  ...state.test3,
});

export default connect(mapStateToProps)(Index);

connect是一个高阶函数,高阶函数就是说把一个函数作为另一个函数的参数。connect接受函数mapStateToProps作为参数,connect(mapStateToProps)返回的也是一个函数,然后再把Index作为这个返回的函数的参数。

页面组件与model关联以后我们是这样去使用它的

this.props.dispatch({type: 'test/saveList',payload: {num: 100}})

  reducers: {
    saveList(state, action) {
     //必须return 否则会报错
      return { ...state, age:18,...action.payload };
    },
  },
  

saveList中的参数 state 和action

state为上次的state。如果连续dispatch了两次reducer,第二次的参数state就是第一次的dispatch之后返回的state,也就是说第一次reducer以后state的值变了,第二次拿到的state就是改变后的state.

action就是dispatch的参数 {type: 'test/saveList',payload: {num: 100}},所以想拿到组件传来的payload参数,要用action.payload。

我们一般把需要传递的数据都放在payload里面,type的值一般是用不到的,所以一般我们会这样写。

 reducers: {
    saveList(state, {payload}) {
      return { ...state, age:18,...payload };
    },
  },

return 修改之后的state,这里返回什么state的内容就会变成什么

effects

格式为*function(action),action和上面一样,effcts里有很多方法,只要会用call put就可以了

  import {getList} from './service'
  //异步请求
  effects: {
    *getList({ payload }, { call, put }) {
    //用call来调用接口
      const res = yield call(getList, payload);
      //用put来调用reducer里的方法 把请求的数据放到state里
      yield put({
        type: 'saveList',
        payload: res,
      });
    },
  },
 

数据传递

image.png

页面或者订阅通过dispatch去调用reducer和effect里的函数,在effect里面去实现services请求,把数据通过reducer放到state里面(reducer操作state里的数据的唯一途径),最后再通过connect吧state和页面关联起来,我们就可以在页面中拿到model里的数据