全局封装loading 加载样式 vue3

该博客介绍了如何在Vue.js项目中实现全局Loading效果,通过维护一个请求计数器来控制Loading的显示与隐藏。同时展示了在axios拦截器中如何设置请求和响应拦截,以在请求开始时显示Loading并在请求结束时关闭,确保了用户体验的一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新建js文件

/**
 * 全局loading效果:合并多次loading请求,避免重复请求
 * 当调用一次showLoading,则次数+1;当次数为0时,则显示loading
 * 当调用一次hideLoading,则次数-1; 当次数为0时,则结束loading
 */
 import { ElLoading } from 'element-plus';
 
 // 定义一个请求次数的变量,用来记录当前页面总共请求的次数
 let loadingRequestCount = 0;
 // 初始化loading
 let loadingInstance;
  
 // 编写一个显示loading的函数 并且记录请求次数 ++
 const showLoading = (target) => {
     if (loadingRequestCount === 0) {
         // element的服务方式 target 我这边取的是表格class
         // 类似整个表格loading和在表格配置v-loading一样的效果,这么做是全局实现了,不用每个页面单独去v-loading
         loadingInstance = ElLoading.service({ target ,text: '加载中...' ,background: 'rgba(0, 0, 0, 0.8)'});
     }
     //解决弹窗打开时loading样式被覆盖问题
     let div = document.querySelector(".el-loading-mask");
     div.style.zIndex ="9999";
     loadingRequestCount++
 }
  
 // 编写一个隐藏loading的函数,并且记录请求次数 --
 const hideLoading = () => {
     if (loadingRequestCount <= 0) return
     loadingRequestCount--
     if (loadingRequestCount === 0) {
         loadingInstance.close();
     }
  }
  
  export {
     showLoading,
     hideLoading
  }

在main.js方法引入文件

// 注入全局方法
import { showLoading, hideLoading } from '@/views/component/loading'
app.config.globalProperties.$showLoading = showLoading
app.config.globalProperties.$hideLoading = hideLoading

还需引入关闭loading的样式放到拦截器中,请求结束关闭
http.js包含拦截器和请求封装
代码如下

import axios from 'axios';
import { ElMessage } from 'element-plus';
import { getToken, removeToken } from '@/utils/token.js';
import Router from '@/router';
import { hideLoading } from '@/views/component/loading'
import qs from 'qs';

//请求拦截器
axios.interceptors.request.use(
  (config) => {
    config.headers['token'] = getToken();
    return config;
  },
  (err) => {
    closeLoading()
    ElMessage.error('系统错误,请求失败!');
  }
);

//响应拦截器
axios.interceptors.response.use(
  (data) => {
    closeLoading()
    if (data.headers.tokenstatus === 'tokenTimeout') {
      removeToken();
      ElMessage.error('登录信息已过期,请重新登录!');
      Router.push('/login').catch((err) => err);
      return data;
    }
    return data;
  },
  (err) => {
    closeLoading()
    switch (err.response.status) {
      case 401:
        removeToken();
        ElMessage.error(err.response.data.body.msg);
        Router.push('/login');
        break;
      default:
        ElMessage.error('系统错误,请求失败!');
        break;
    }
    if (!err.response.status) {
      closeLoading()
      return { data: err.response };
    }
  }
);

/**
 * axios请求的封装
 * axios默认请求类型为application/json
 */
axios.defaults.baseURL = '/api/';
// 允许跨域携带cookie信息
axios.defaults.withCredentials = true;
// 表示所有axios请求都是跨域请求,那么每次请求之前都会发送一个Options(预检)请求,用于询问后端是否允许本次请求。所以需要后端也进行相应的设置。
axios.defaults.crossDomain = true;

// post请求
export const postRequest = (url, params, isList = false) => {
  params = notNull(params);
  let transformRequest = [
    function (data) {
      let ret = '';
      for (let i in data) {
        ret += encodeURIComponent(i) + '=' + encodeURIComponent(data[i]) + '&';
      }
      return ret;
    },
  ];
  if (isList) {
    transformRequest = [
      function (data) {
        // 解决传递数组变成对象的问题
        return qs.stringify(data, { arrayFormat: 'indices', allowDots: true });
      },
    ];
  }
  return axios({
    method: 'post',
    url: url,
    data: params,
    //axios自带的数据操作方法,可以在请求前将数据格式化
    transformRequest: transformRequest,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
    },
  });
};

// get请求
export const getRequest = (url, params) => {
  return axios({
    method: 'get',
    url: url,
    params: params,
  });
};

// 后台返回流的请求
export const postStreamRequest = (url, params) => {
  return axios({
    method: 'post',
    url: url,
    params: params,
    responseType: 'arraybuffer',
  });
};

export const notNull = (data) => {
  for (let k1 in data) {
    if (data[k1] === null) {
      data[k1] = '';
      continue;
    }
    if (Object.prototype.toString.call(data[k1]) === '[object Object]') {
      notNull(data[k1]);
      continue;
    }
    if (Array.isArray(data[k1])) {
      for (let k2 in data[k1]) {
        if (
          Object.prototype.toString.call(data[k1][k2]) === '[object Object]'
        ) {
          notNull(data[k1][k2]);
        }
      }
      continue;
    }
  }
  return Object.assign({}, data);
};

function closeLoading(){
  try{
    hideLoading()
  }catch(e){

  }
}

使用示例

async function loadZyzhzdjkftjOptionList() {
//请求前使用
   proxy.$showLoading()
  const { data: res } = await proxy.$postRequest(
    "接口"
  );
  if (res.status == 200) {
  //请求成功后隐藏
  } else {
    proxy.$message.error(res.msg);
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值