使用 Axios 加全局 Loading 效果详解

在现代 web 开发中,用户体验至关重要。对此,我们通常希望在用户进行请求的时候给予视觉反馈,例如显示一个 loading 动画。这在使用 Axios 进行 HTTP 请求时尤为重要,因为 Axios 是最流行的 JavaScript HTTP 客户端之一。

本篇文章将介绍如何在 Axios 中实现全局 loading 效果,包括代码示例,并配合使用 mermaid 生成关系图和序列图。

1. Axios 简介

Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和节点.js。它支持请求和响应拦截,转换请求数据和响应数据,取消请求等功能。由于其简单易用的特性,它成为了现代前端开发中的重要工具。

2. 全局 Loading 效果的实现原理

实现全局 loading 效果的基本思路如下:

  1. 请求拦截器:在请求发出之前,显示 loading 动画。
  2. 响应拦截器:在成功接收到响应后,隐藏 loading 动画。
  3. 错误处理:无论请求是否成功,均需要 在捕获到错误的情况下隐藏 loading 动画。

以下是简单的关系图,展示了 Axios 请求过程中 loading 的状态变化:

erDiagram
    REQUEST {
        string url
        string method
        string data
    }
    RESPONSE {
        string data
        int status
    }
    LOADING {
        boolean isLoading
    }
    REQUEST ||--o{ LOADING : starts
    RESPONSE ||--o{ LOADING : ends

3. 创建全局 Loading 组件

在 Vue.js 应用中,我们可以通过创建一个全局 loading 组件来进行 loading 状态的管理。

创建 Loading 组件

首先,我们创建一个简单的 loading 组件 Loading.vue

<template>
  <div v-if="isLoading" class="loading-overlay">
    <div class="loading-spinner"></div>
  </div>
</template>

<script>
export default {
  computed: {
    isLoading() {
      return this.$store.state.isLoading;
    }
  }
}
</script>

<style>
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.loading-spinner {
  border: 8px solid rgba(255, 255, 255, 0.3);
  border-left-color: white;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>

配置 Vuex 管理 Loading 状态

我们使用 Vuex 来管理 loading 状态,以便在组件之间共享该状态。

创建 Store
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    isLoading: false,
  },
  mutations: {
    SET_LOADING(state, status) {
      state.isLoading = status;
    }
  },
});

4. 配置 Axios 拦截器

接下来,我们为 Axios 添加请求和响应拦截器,以便在请求期间显示 loading。

Axios 配置

// axiosConfig.js
import axios from 'axios';
import store from './store';

axios.interceptors.request.use(
  config => {
    store.commit('SET_LOADING', true); // 开始请求时显示 loading
    return config;
  },
  error => {
    store.commit('SET_LOADING', false); // 请求出错时隐藏 loading
    return Promise.reject(error);
  }
);

axios.interceptors.response.use(
  response => {
    store.commit('SET_LOADING', false); // 请求成功时隐藏 loading
    return response;
  },
  error => {
    store.commit('SET_LOADING', false); // 请求失败时隐藏 loading
    return Promise.reject(error);
  }
);

export default axios;

5. 使用全局 Loading 组件

现在我们需要在我们的根组件中使用 Loading 组件。

修改 App.vue

<template>
  <div id="app">
    <Loading />
    <router-view />
  </div>
</template>

<script>
import Loading from './components/Loading.vue';

export default {
  components: {
    Loading
  }
}
</script>

6. 完整代码示例

将以上所有代码综合起来,我们的项目结构大致如下:

src
├── components
│   └── Loading.vue
├── store.js
├── axiosConfig.js
└── App.vue

7. 功能验证

在编写了以上代码后,你可以通过发起一些 HTTP 请求来验证加载效果。比如,你可以在某个组件的 mounted 钩子中发起请求,观察 loading 是否如预期显示和隐藏。

示例请求:

import axios from './axiosConfig';

export default {
  async mounted() {
    try {
      const response = await axios.get('
      console.log(response.data);
    } catch (error) {
      console.error(error);
    }
  }
}

8. 序列图展示

最后,让我们用序列图表示 Axios 请求过程中的 Loading 状态变化:

sequenceDiagram
    participant U as User
    participant C as Component
    participant S as Store
    participant A as Axios

    U->>C: send request
    C->>S: SET_LOADING(true)
    S-->>C: update loading state
    C->>A: axios request
    A->>A: handling request...
    A->>S: response
    S-->>C: SET_LOADING(false)

9. 结论

通过上述实现,我们可以很方便地在 Vue.js 应用中使用 Axios 进行全局 loading 效果的显示和隐藏。这样的做法不仅改善了用户体验,还使得我们的代码结构更加整洁。希望本文对你理解和实现 Axios 全局 loading 效果有所帮助!