dva 如何異步獲取接口數據

說在前面

  • 關於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獲取statejavascript

    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 。html

新建一個一個model/users.jsvue

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文件java

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

這裏我主要在effects 定義了一個handleGetSearch方法,
這個方法簡單理解:react

一、paload是接口的參數,這裏打印一下
二、searchRspCallBack是一個回調方法,
  主要是在接口正常調用以後將響應內容在頁面層使用
三、yield call(getSearch, payload);是一個異步調用接口參數的方法
四、上述中的if判斷主要是說在接口響應到的數據爲我與後臺正肯定義的返回碼才進行相應的操做,
好比這裏我跟後臺約定的是status === 0正常 status === 1 打印後臺返回的錯誤信息
五、searchRspCallBack(response.data.result)
  調用傳過來的回調將接口返回數據做爲參數傳進去

reducers方法:用於執行同步操做,改變state等git

return {
    ...state,
    searchRsp: payload.data,
    }
改變model中state的searchRsp值爲接口返回的響應內容

第二步、使用model中的方法

model中異步獲取數據的方法定義好以後如何使用呢?github

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 。web

這裏使用註解的方法使用connectajax

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

上述dispatch的簡單解釋:vuex

一、type爲要調用的哪一個model中的哪一個方法,

二、payload爲傳的參數,這裏傳了一個keyword與limit數量過去

三、searchRspCallBack: this.handleSearchRspCallBack的意思是將本地的一個方法做爲參數傳遞到model中,
若是model中正確響應以後將響應的內容做爲參數傳遞到這個方法中,
而後我本地寫一個handleSearchRspCallBack方法用來接收響應
這樣我在component層就能夠拿到接口響應的內容了

這是我用來獲取接口異步數據的方法第一種,還有一種就是以前在model中執行了reducer同步方法將接口返回的數據保存在了model中的state裏面,在componentWillReceiveProps鉤子函數也能夠拿到咱們須要的響應

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

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

簡單的總結

一、先在model中定義一個方法用來執行異步調用接口的方法,能夠直接使用回調方法的方法將響應做爲參數回調,也可使用同步reducer的方法將數據保存在state中,後面component層去取model中state的值

二、兩種方法均可以獲取到異步調用接口返回的響應,第一種好須要定義一個回調方法,第二種獲取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中能夠獲取到數據

原文首發

相關文章
相關標籤/搜索