描述: 添加全局loading目的是减少页面写v-loading指令, 这样我们只需要配置参数就可以控制每个请求是否需要loading,并且可以配置正在loading的元素, 这里通过请求时配置header参数进行控制, 网上都有教程了,这里也是记录一下,方便自己以后查看.

实现代码:
我loading方法放在utils文件夹下

import { debounce } from "./funDebounce";
//import { Loading } from 'element-ui' // 装包方式这样引入,我这里通过cdn引入,通过window.ELEMENT调用
// loading对象
let loading;

// 当前正在请求的数量
let needLoadingRequestCount = 0;

// 显示loading
export function showLoading(target) {
  // 后面这个判断很重要,因为关闭时加了抖动,此时loading对象可能还存在,
  // 但needLoadingRequestCount已经变成0.避免这种情况下会重新创建个loading
  console.log(needLoadingRequestCount, loading);
  if (needLoadingRequestCount === 0 && !loading) {
    loading = window.ELEMENT.Loading.service({ // 通过cdn引入的element-ui
      lock: true,
      text: "加载中...",
      background: "rgba(255, 255, 255, 0.7)",
      target: target || "#micro-apps-container"
    });
  }
  needLoadingRequestCount++;
}

// 隐藏loading
export function hideLoading() {
  needLoadingRequestCount--;
  needLoadingRequestCount = Math.max(needLoadingRequestCount, 0); // 做个保护
  if (needLoadingRequestCount === 0) {
    // 关闭loading
    toHideLoading();
  }
}

// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次。防止连续请求时, loading闪烁的问题。
let toHideLoading = debounce(() => {
  loading.close();
  loading = null;
}, 300);

上面用到的 防抖节流函数:

/**
 * @desc 函数防抖
 * @param func 目标函数
 * @param wait 延迟执行毫秒数
 * @param immediate true - 立即执行, false - 延迟执行
 *   立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果
   非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
 */
export function debounce(func, wait, immediate) {
  let timer;
  return function () {
    let context = this;
    let args = arguments;

    if (timer) clearTimeout(timer);
    if (immediate) {
      let callNow = !timer;
      timer = setTimeout(() => {
        timer = null;
      }, wait);
      if (callNow) func.apply(context, args);
    } else {
      timer = setTimeout(() => {
        func.apply(context, args);
      }, wait);
    }
  };
}

// 定时器版-节流
export function throttle(func, wait) {
  let timeout;
  return function () {
    let context = this;
    let args = arguments;
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null;
        func.apply(context, args);
      }, wait);
    }
  };
}

引入我们配置全局拦截文件:
这边只是介绍了loading引入,其他拦截配置大家按照自己项目配置.

import { showLoading, hideLoading } from "@/utils/requestLoading";
import axios from 'axios'
let configChace = null; // 存放请求参数,在进入错误时候也关掉loading
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 判断当前请求是否设置了不显示Loading,默认显示
  if (config.headers.showLoading) {
    showLoading(config.headers.loadingTarget); // 如果设置了targer,使用设置的target,比如el-table
    configChace = config;
  }
  return config;
  }, function (error) {
    // 对请求错误做些什么
         // 关闭loading
    if (configChace.headers.showLoading) {
      hideLoading();
      configChace = null;
    }
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
     // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
    if (response.config.headers.showLoading) {
      hideLoading();
    }
    return response;
  }, function (error) {
    // 对响应错误做点什么
     // 关闭loading
    if (configChace.headers.showLoading) {
      hideLoading();
      configChace = null;
    }
    return Promise.reject(error);
  });

使用:
通过配置header参数控制是否要Loding:

import { axios, post } from "./settings"; // 封装好的请求方法

export const stuSubjectApi = params => {
  return axios({
    url: "xxx",
    method: "get",
    params,
    headers: { showLoading: true, loadingTarget: 'xxx' }
  });
};

然后在项目调用接口就可以了.

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐