用React+Antd封裝Axios實現全局Loading效果

前言

今天在作react後臺管理的時候要實現一個全局Loading效果,一般使用axios庫與後端進行數據交互。爲了更好的用戶體驗,在每次請求前添加一個加載效果,讓用戶知道在等待加載。css

要實現這個功能,咱們能夠在每一個組件請求手動添加加載效果返回後再將其隱藏,但若是每一個請求都這麼作,就要作屢次重複設置顯得很麻煩,但好處是能夠設置定製多種請求效果。但考慮到該項目場景爲後臺管理系統,給管理員使用,花樣能夠不用搞太多,統一優雅便可,故採起全局設置loading效果。react

開發版本

"react": "^16.13.1",
"antd": "^4.0.4",
"axios": "^0.19.2"

代碼說明

  1. 經過 axios 提供的請求攔截和響應攔截的接口,控制 loading 的顯示或者隱藏。在此我還設置了沒有網絡和網絡超時的提示信息
  2. 採用antd的Spin組件來實現loading效果,message組件來進行消息提示(antd.css這裏沒有引入,是由於我設置了按需加載)
  3. 定義變量requestCount做爲計數器,確保同一時刻若是有多個請求的話,不會同時添加多個 loading,而是隻有1個,並在全部請求結束後纔會隱藏 loading。
  4. 默認全部請求都會自動有 loading 效果。若是某個請求不須要 loading 效果,能夠在請求 headers 中設置 isLoading 爲false。

步驟

1.在src目錄下新建一個文件axios.jsios

import axios from 'axios';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { message, Spin } from 'antd';

const Axios = axios.create({
    // baseURL: process.env.BASE_URL, // 設置請求的base url
    timeout: 20000, // 設置超時時長
})

// 設置post請求頭
Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'

// 當前正在請求的數量
let requestCount = 0

// 顯示loading
function showLoading () {
    if (requestCount === 0) {
        var dom = document.createElement('div')
        dom.setAttribute('id', 'loading')
        document.body.appendChild(dom)
        ReactDOM.render(<Spin tip="加載中..." size="large"/>, dom)
    }
    requestCount++
}

// 隱藏loading
function hideLoading () {
    requestCount--
    if (requestCount === 0) {
        document.body.removeChild(document.getElementById('loading'))
    }
}

// 請求前攔截
Axios.interceptors.request.use(config => {
   // requestCount爲0,才建立loading, 避免重複建立
    if (config.headers.isLoading !== false) {
        showLoading()
    }
    return config
}, err => {
    // 判斷當前請求是否設置了不顯示Loading
    if (err.config.headers.isLoading !== false) {
        hideLoading()
    }
    return Promise.reject(err)
})

// 返回後攔截
Axios.interceptors.response.use(res => {
    // 判斷當前請求是否設置了不顯示Loading
    if (res.config.headers.isLoading !== false) {
        hideLoading()
    }
    return res
}, err => {
    if (err.config.headers.isLoading !== false) {
        hideLoading()
    }
    if (err.message === 'Network Error') {
        message.warning('網絡鏈接異常!')
    }
    if (err.code === 'ECONNABORTED') {
        message.warning('請求超時,請重試')
    }
    return Promise.reject(err)
})

// 把組件引入,並定義成原型屬性方便使用
Component.prototype.$axios = Axios

export default Axios

2.添加loading樣式在共用的css文件裏axios

#loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    font-size: 20px;
}

3.axios請求後端

// 1. 引入自定義axios文件路徑
// 2. 引入共用css文件(loading樣式)
// 3. 在react組件中正常寫法請求url便可
componentDidMount () {
    axios({
      url: '/manage/statistic/base_count.do'
    }).then(res => {
      this.setState(res.data)
    })
}

不加loading效果,這樣寫網絡

axios({
  url: '/manage/statistic/base_count.do',
  headers: {
    'isLoading': false
  }
}).then(res => {
  this.setState(res.data)
})

效果

相關文章
相關標籤/搜索