通过axios拦截器与element-ui Loading 加载组件实现页面加载监听功能

3,111 阅读3分钟

  我们并非只有一次生命;
  如果我们能够阅读,
  就能够随心所欲地拥有多次生命和多种活法。

                ————塞缪尔·早川

说明

最近做项目过程中,由于网络不佳或者请求数据数据过大,进入页面时,会出现空白,用户体验不好,所以加入加入一个数据未出现之前的加载效果。

具体实现步骤是:

  1. 接口定义,在axios的get与post方法中通过headers添加自定义头部信息来传递值
  2. 使用axios的拦截器获取到自定义头部数据后做出相关处理
  3. 配置element-ui Loading 加载组件

接口定义

参数说明

  • condition

    {}||自定义hash对象,必传

  • headerConfig

参数 类型 作用 默认值
showLoading boolean 在发起axios请求时,是否显示loading动画 false
loadingTarget string loading动画要挂载的dom选择器 body节点

get方法

get类型接口

var getFunc = function(condition, headerConfig) {
  return axios.get(`/v1/items/source/search?action=getimages`, {
    params: condition,
    headers: headerConfig
  });
};

页面调用

var headerConfig = {
  showLoading: true,
  loadingTarget: "#box-nodata"
};

var condition = {
    searchTerms: this.q,
    from: this.fromPage,
    size: this.pageSize
};

getFunc(condition, headerConfig)
.then(res => {
  //后台传过来的total为string类型,需要转换成number类型
  this.totalNum = parseInt(res.total);
  this.itemList = res.result;
})
.catch(err => {
  this.$message({
    showClose: true,
    type: "error",
    message: `数据加载出错。原因:${err.message}`
  });
});

post方法

post类型接口

var postFunc = function(condition, headerConfig) {
  return axios.post(`/v1/search/item`, condition, { 
    headers: headerConfig 
  });
};

注意在post方法中,condition与headers的赋值方式

页面调用

var headerConfig = {
  showLoading: true,
  loadingTarget: "#box-nodata"
};

var condition = {
    searchTerms: this.q,
    from: this.fromPage,
    size: this.pageSize
};

postFunc(condition, headerConfig)
.then(res => {
  //后台传过来的total为string类型,需要转换成number类型
  this.totalNum = parseInt(res.total);
  this.itemList = res.result;
})
.catch(err => {
  this.$message({
    showClose: true,
    type: "error",
    message: `数据加载出错。原因:${err.message}`
  });
});

在get与post方法中,condition是作为查询参数,而headerConfig作为我们通过axios请求时额外传递的参数

axios拦截器处理

通过axios拦截器,我们在请求与获取数据后做加载的相关处理,在发起请求时我们先显示正在加载条,当获得数据后关闭加载条,代码如下:

import axios from "axios";
import { Loading } from "element-ui";
import { response_handle } from "./response_handle";

// loading对象
let loading;

// 请求合并只出现一次loading
// 当前正在请求的数量
let needLoadingRequestCount = 0;

/* 请求拦截器 */
axios.interceptors.request.use(
  config => {
    // 如果当前请求要显示Loading
    if (config.headers.showLoading)
    showLoading(config.headers.loadingTarget);
    return config;
  },
  err => {
    hideLoading();
    return Promise.resolve(err);
  }
);

/* 响应拦截器 */
axios.interceptors.response.use(
  response => {
    hideLoading();
    /* 这里对返回的response做了简单的处理,
    就不需要对每个接口在做处理了 */
    return response_handle(response);
  },
  error => {
    //判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
    hideLoading();
    return Promise.reject(error);
  }
);

/* 显示loading */
function showLoading(target) {
  // 后面这个判断很重要,因为关闭时加了抖动,此时loading对象可能还存在,
  // 但needLoadingRequestCount已经变成0.避免这种情况下会重新创建个loading
  if (needLoadingRequestCount === 0 && !loading) {
    loading = Loading.service({
      lock: true,
      text: "数据加载中,请耐心等候...",
      background: "rgba(255, 255, 255 ,1)",
      target: target || "body"
    });
  }
  needLoadingRequestCount++;
}

/* 隐藏loading */
function hideLoading() {
  if (needLoadingRequestCount <= 0) return;
  needLoadingRequestCount--;
  if (needLoadingRequestCount === 0 && loading) {
    loading.close();
    loading = null;
  }
}

调用element-ui的Loading 加载组件服务

其中Loading插件用了element-ui现成的组件,以服务的方式调用。

引入 Loading 服务:

import { Loading } from 'element-ui';

在需要调用时:

Loading.service(options);

其中 options 参数为 Loading 的配置项。