# loading加载动画

* 参考: <https://www.jianshu.com/p/a5542618272a>

## vue elementUI axios实现的全局loading加载动画

在请求较多的应用中，loading是必不可少的，否则人们不是认为程序卡了就是认为设备卡了

普通的项目中，每次请求基本都要手动写一下loading的出现和消失，且不说有些麻烦，而且在ajax异步的情况下，如果做不好loading同步，经常会出现loading不出现的情况，而且不同浏览器兼容性较差。

## 一.概念

在vue项目中，有了统一配置机制，可以实现对loading的配置使每次请求前自动出现loading，请求后loading消失

顺带一提，本来ajax调为同步模式挺好用的，但axios没有同步功能

关于elementui的loading，教程在这里：[https://element.eleme.cn/2.0/#/zh-CN/component/loading](https://links.jianshu.com/go?to=https%3A%2F%2Felement.eleme.cn%2F2.0%2F%23%2Fzh-CN%2Fcomponent%2Floading)

![](https://upload-images.jianshu.io/upload_images/20669848-bc3cd8bd73d792c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1097/format/webp)

图片发自简书App

* 第一种方法是在需要出现loading的地方加着`v-loading` 指令，此方法在小应用中可以用，在大型应用中显得过于繁琐
* 第二种是服务方式：

![](https://upload-images.jianshu.io/upload_images/20669848-feabd97329c51f4d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1123/format/webp)

图片发自简书App

> 最后一句话是重点，也就是说如果页面有多个请求一起请求，如果都使用一个服务loading，很可能会出现较快结束请求的那个直接把loading关了，而请求时间长的还没有结束请求。这点在下面设计的时候需要关注

## 二.实现

在main.js中，引入vue,axios,elementui

```tsx
import Vue from 'vue'
import App from './App'
import router from './router'

import elementui from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

import axios from 'axios'

import {Loading} from 'element-ui'

//修改原型链，全局使用axios,这样之后可在每个组件的methods中调用$axios命令完成数据请求
Vue.prototype.$axios=axios
// 安装各类插件
Vue.use(elementui)

let loading;
//内存中正在请求的数量
let loadingNum=0;
function startLoading() {    
    if(loadingNum==0){
        loading = Loading.service({
          lock: true,
          text: '拼命加载中...',
          background:'rgba(255,255,255,0.5)',
        })
    }
    //请求数量加1
    loadingNum++;
}
function endLoading() {
    //请求数量减1
    loadingNum--
    if(loadingNum<=0){
        loading.close()
    }
}

//请求数据拦截器
axios.interceptors.request.use(request => {
  startLoading();
  return request
}, err => {
  return Promise.reject(err);
});


//接收响应拦截器
axios.interceptors.response.use(response => {
  endLoading();
  return response
}, err => {
  endLoading();
  if (err && err.response) {
    switch (err.response.status) {
      case 400: err.message = '请求错误(400)'; break;
      case 401: this.$router.push('/login'); break;
      case 403: err.message = '拒绝访问(403)'; break;
      case 404: err.message = '请求出错(404)'; break;
      case 408: err.message = '请求超时(408)'; break;
      case 500: err.message = '服务器错误(500)'; break;
      case 501: err.message = '服务未实现(501)'; break;
      case 502: err.message = '网络错误(502)'; break;
      case 503: err.message = '服务不可用(503)'; break;
      case 504: err.message = '网络超时(504)'; break;
      case 505: err.message = 'HTTP版本不受支持(505)'; break;
      default: err.message = `连接出错(${err.response.status})!`;
    }
  } else {
    err.message = '连接服务器失败!'
  }
  message.error(err.message);
  return Promise.reject(err);
});


/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App },
  data: {
    eventHub: new Vue()
  } 
})
```

因为loading只是一个实例，所以需要加入了请求个数控制，每次请求开始加一个，请求结束减一个，当请求个数为0时才使loading消失。

这样配置后应用中其他组件每次调用axios请求都会自动出现消失loading。

## 三.解决自定义样式问题

到这里，每次请求的loading样式都一模一样了，如果有的请求需要其他的loading样式怎么办呢？

利用服务中loading只有一个实例的原理，只需要在请求之前就创建出一个loading实例，因为创建一个实例后再调用会继续使用这个实例，loading的名字就变了

例：

![](https://upload-images.jianshu.io/upload_images/20669848-b6d7b0ff281d46cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/838/format/webp)

图片发自简书App

在每个需要变样式的请求前面加上这个即可


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://close.gitbook.io/yun-wei-bi-ji/centos/vue/loading-jia-zai-dong-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
