dva 如何异步获取接口数据

栏目: JavaScript · 发布时间: 5年前

内容简介:dva里的model主要是用来开始处理数据和逻辑的。dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。新建一个一个

说在前面

  • 关于redux的框架有很多,这里我用到的是阿里云谦大大的dva( 项目地址 ),这里主要记录下工作中是如何使用dva来异步获取接口数据的。
  • 文末更新至20190619

更新(2019.0619)

  • 最近发现这篇文章虽然写的很烂,但是很多人都能搜到进来瞅两眼,想着再更新一点吧。主要补充一下 dva 的几个关键词的作用

state的作用

  • State 表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值);操作的时候每次都要当作不可变数据(immutable data)来对待,保证每次都是全新对象,没有引用关系,这样才能保证 State 的独立性,便于测试和追踪变化。
  • 在每一个 model 中定义 state ,用于分模块管理全局状态

effects的作用

  • 进行异步操作的地方(ajax...),底层引入了 redux-sagas 做异步流程控制,由于采用了 generator 的相关概念,所以将异步转成同步写法
  • 类似于 vuex 中的 Action ,包含异步操作,在 vuex 中用于提交 mutation ,从而变更 state ,在 dva 中用于提交 reducer ,用于修改 state

Reducer的作用

  • 同步方法,唯一可以修改 state 的地方,通过 effect 通过 actions 传入的值修改 state
  • 类似于 vuexmutation

Subscription的作用

  • 订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。

payload关键字

  • 一般作为参数含义,由UI层通过 dispatch 一个 payload 参数在 model 文件中使用

call

  • 结合 yield call 发起ajax请求
//getDetailDiscount 接口名
//payload 参数
yield call(getDetailDiscount, payload)

put

  • 使用 put 关键词提交 Reducer
//doDiscounts 一个名字为doDiscounts的同步方法 修改state
yield put({type: 'doDiscounts', payload: response.data});

select

  • effect 中可以通过 select 获取 modelstate
  • 定义 state
state:{
     num:1
 }
  • 定义 effect
effect:{
     *getNum({payload},{select}){
         //获取state中的num
         const num = yield select(state => state.num) 
     }
 }
  • model 获取 state

    other字段为 modelnamespace

effect:{
     *getOtherNum({payload},{select}){
         //获取state中的num
         const num = yield select(state => state.other.num) 
     }
 }

这里是正文

第一步、定义model

dva里的model主要是用来开始处理数据和逻辑的。

dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。

新建一个一个 model/users.js

export default {
  namespace: 'users',
  state: [],
  reducers: {
     doSearch (state, { payload}){
      return {
        ...state,
        searchRsp: payload.data,
      }
    },
  },
  effects:{
  * handleGetSearch({payload, searchRspCallBack}, {call, put}) {
      LogTag('****************************handleGetSearch req*************', payload);
      const response = yield call(getSearch, payload);
      LogTag('****************************handleGetSearch rsp*************', response);
      if (response.status === 200 && response.data.status === 0) {
        searchRspCallBack(response.data.result)
      } else if (response.status === 200 && response.data.status === 1) {
        message.error(response.data.msg)
        yield put({
          type: 'doSearch',
          payload: response.data,
        });
      }
      
  },
  subscriptions :{
      
  }
};

新建ApiService.js文件

import request from '../utils/request';
import {stringify} from 'qs';
/*
* 搜索
* */
export async function getSearch(params) {
  return request(`/search?${stringify(params)}`);
}

这里我主要在effects 定义了一个 handleGetSearch 方法,

这个方法简单理解:

1、paload是接口的参数,这里打印一下
2、searchRspCallBack是一个回调方法,
  主要是在接口正常调用之后将响应内容在页面层使用
3、yield call(getSearch, payload);是一个异步调用接口参数的方法
4、上述中的if判断主要是说在接口响应到的数据为我与后台正确定义的返回码才进行相应的操作,
比如这里我跟后台约定的是status === 0正常 status === 1 打印后台返回的错误信息
5、searchRspCallBack(response.data.result)
  调用传过来的回调将接口返回数据作为参数传进去

reducers 方法:用于执行同步操作,改变state等

return {
    ...state,
    searchRsp: payload.data,
    }
改变model中state的searchRsp值为接口返回的响应内容

第二步、使用model中的方法

model中异步获取数据的方法定义好之后如何使用呢?

this.props.dispatch({
      type: 'users/handleGetSearch',
      payload: {
        keywords: this.state.searchText,
        limit: this.state.limit
      },
      searchRspCallBack: this.handleSearchRspCallBack
})

handleSearchRspCallBack = (rsp)=>{
    LogTag(rsp)
}

这是dva中使用dispatch调用model中方法的写法,注意在使用此方法之前要先使用 connect 将model与component连接起来,如果你熟悉 redux,这个 connect 就是 react-redux 的 connect 。

这里使用注解的方法使用connect

@connect(({users, loading}) => ({
  users,
}))

上述dispatch的简单解释:

1、type为要调用的哪个model中的哪个方法,

2、payload为传的参数,这里传了一个keyword与limit数量过去

3、searchRspCallBack: this.handleSearchRspCallBack的意思是将本地的一个方法作为参数传递到model中,
如果model中正确响应之后将响应的内容作为参数传递到这个方法中,
然后我本地写一个handleSearchRspCallBack方法用来接收响应
这样我在component层就可以拿到接口响应的内容了

这是我用来获取接口异步数据的方法第一种,还有一种就是之前在model中执行了 reducer 同步方法将接口返回的数据保存在了model中的state里面,在componentWillReceiveProps钩子函数也可以拿到我们需要的响应

componentWillReceiveProps(nextProps){
    if(nextProps){
      LogTag(nextProps.users.searchRsp)
    }
  }

上述中 nextProps.users.searchRsp 就是接口返回的值了

简单的总结

1、先在model中定义一个方法用来执行异步调用接口的方法,可以直接使用回调方法的方法将响应作为参数回调,也可以使用同步reducer的方法将数据保存在state中,后面component层去取model中state的值

2、两种方法都可以获取到异步调用接口返回的响应,第一种好需要定义一个回调方法,第二种获取model中state值需要定义state,在不同的场景使用不同的方法

文章补充:2019.6.1

  • 使用 callback 非常的不优美,这里官方其实早已提供 promise 的写法
*handleUpdateBasicInfo({ payload, user }, { call, put, select }){
      const response = yield call(postUpdateBasicInfo, payload);
      if (response && response.status === 0) {
        return response.data
      }
    },
    //这里在effect中直接return 我们想知道的结果
    
    handleUpdateBasicInfo = (params) => {
    const { dispatch } = this.props;
    dispatch({
      type: 'user/handleUpdateBasicInfo',
      payload: {
        ...params,
      },
    }).then(res=>{
      console.log('res',res)
    })
  };
  //这里then中可以获取到数据

原文首发


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mastering Bitcoin

Mastering Bitcoin

Andreas M. Antonopoulos / O'Reilly Media / 2014-12-20 / USD 34.99

Mastering Bitcoin tells you everything you need to know about joining one of the most exciting revolutions since the invention of the web: digital money. Bitcoin is the first successful digital curren......一起来看看 《Mastering Bitcoin》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具