umi3 使用 dva 的流程及理解(model数据使用教程)

在dva中主要分3层,models,services,components,其中models是最重要概念,这里放的是各种数据,与数据交互的应该都是在这里。services是请求后台接口的方法。components是组件了。

本文主要讲model的使用.
下面是model的基本结构

{   namespace: String, // 命名空间名字,必填     
//namespace: 'global' 说明以下此处的dva命名空间为 global,即你调用的时候需要采用 global.XXX 的形式   
state: Object, // 状态   
reducer: Object, // 同步更新 state 修改状态  
 effects: Object, // 副作用:处理异步逻辑     
 //当数据需要从服务器获取时,需要发起异步请求,请求到数据之后,通过调用 Reducers更新数据到全局state   
 subscriptions: Object // 订阅数据源
 }

1.reducer

用来处理同步操作。如果不需要调接口时候,我们前台传递的 action(不懂的小伙伴不着急,下面有微讲解) 可以直接调用 reducers
里的方法。

reducer是一个函数,接收state 和 action,返回老的或新的state。 即: save(state, action) {
return { …state, …action.payload }; },

state:为当前 Model 下的所有 state 值,可以 console.log(state) 看一下输出就知道了。
action:当前台页面需要进行数据操作时,就会创建一个 action,action 存放了传递过来需要对当前 state 进行改变的数据。

reducers:{
changeTitle(state, { payload: { num }){ 
//changeTitle可以理解为一个方法名 
//payload:就是 action 里传递过来的数据。
//num 是传过来的,名字随便起,不是state中的num,这接收一个action

return {...state,...num}

//return:返回的是新的 state。等于舍弃了旧的 state,重新 return 一个新的 state 作为当前 Model 的 state。
//一般情况下,我们要解开旧的 state,将它重新赋值给新的 state。...state 为 ES6 语法。
//将操作完成得数据累加到 return 中。
//同名的数据会覆盖,所以不用担心旧的 state 值会影响到新设置的值。
//不同名的数据会追加。

},
//页面调用

//页面使用dispatch进行使用
this.props.dispatch({
      type: 'pageModel/changeTitle',  //namespace+需要调用的reducer方法
      payload: 'Hello World',
    });
  };

2.effects

用来处理异步操作。如果需要调取接口的话,前台页面就需要调用 effects 里的方法。

将数据取出来,在传递给 reducers 里的方法进行数据操作和同步 state。

Dva 中的异步操作都放到 effects 中管理,基于 Redux-saga 实现 Effect 是一个 Generator函数,内部使用 yield 关键字,标识每一步的操作

每一个 effect 都可以接收两个参数:

  1. 包含 dispatch 携带参数 payload 的 action 对象
  2. dva 提供的 effect 函数内部的处理函数集

第二个参数提供的处理函数中,常用的有 call、put、select call: 执行异步函数 put: 发出一个 Action,类似于
dispatch 触发reducer改变state select: 返回 model 中的 state //用于从state里获取数据

1.call

 *deleteOne({ payload }, { call }) {
 //deleteOne方法名,payload是传来的参数,是个对象,如果没参数可以写成{_,{call, put}}
//*:这个 * 符号,可能小伙伴们不熟悉,简单点,只要记住每个 effects 里方法前面都加上 * 即可。
//(这表明它是一个异步函数,里面可以使用 yield 等待其他异步函数执行结果。)

//payload:当前台页面需要进行数据操作时,就会创建一个 action,
//action 存放了传递过来需要对当前 state 进行改变的数据。
//payload 就是存放在 action 里面的数据。


const rsp = yield call(cardsService.deleteOne,{num:payload.numCount});
//call:与后台服务端接口进行交互。
//第一个传参:后台服务器接口对应的名称。第二个参数:入参。
//cardsService是引入service层那个js的一个名字,num是后台要求传的参数,rsp就是后台返回来的数据
// 请求成功之后,调用 reducer 更新 state
service中异步请求(cardsService.js)
request 是我们封装的一个网络请求库   
 async function deleteOne(data) {
   return request("queryFromApi", {
      data,
    method: "post",
    dataType: "payload"
  })   }

2.select

 *deleteOne({ payload }, { select, put }) {
  effects:{
    const m = yield select((state) => state.test.num)
    //select就是用来选择上面state里的数据
    }

3.put

yield put({
   type: "addNum",
 // put:用来发出事件,即 action。一般调用 reducers 下的方法进行同步数据。
//type:该 Model 层里 reducers 下的方法名。
//payload:参数的传递。
      payload: {
     num: data, 
   // 把后台返回的数据赋值给了num
  //假如那个reducer中方法是由这里effects去触发的,那个num名必须是这里名字num,如果reducer中方法不是这触发,那名字可随便起
      return rsp;
    },
}
}

3.subscriptions

// 订阅监听,比如我们监听路由,进入页面就如何,可以在这写
  setup ({ dispatch, history, query }) {
   return history.listen(
   async ({ pathname, search, query}) => {
      if (pathname==="/testdemo") 
      {// 当进入testdemo这路由,就会触发fetchUser方法
              dispatch({ type: "fetchUser" })
              }
          })
      }

4.connect

connect 连接 Model 和 Route 页面下的数据
dva 有提供 connect 方法。只要在每个 Routes 页面导入下面的代码即可。

import { connect } from 'dva';

对于组件:
我们在最后导出时使用 connect 进行与 Models 的连接。

export default connect(({index}) => ({index}))(IndexPage);

//解释一下 index:

index 为 Model 层里面的 namespace。

前台调用 Model 层方法

const { dispatch } = this.props; 
//在 dva 中,可以通过 `this.props` 直接取得 `dispatch`
dispatch ({
    type:'example/fetch',  //指定哪个 model 层里面的哪个 方法
    payload:{name:'exampleNew'}, 
     //需要传递到 model 层里面的参数。
     //payload 为固定用法(我自己的理解)。
})

5.parame和query传值

query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示

  • 14
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值