The problem

In a real project, the front end sending a request for data to refresh the page is a familiar operation. The speed of the request response is related to the complexity of business logic and network environment. It is very likely that there will be request delay. If we do not deal with the interaction before and after the request response, then the page will not have any prompt information before the request response is successful, which will affect the user experience very much. But how to handle the loading state individually for each request is a lot of work. Axios is a common request library for our development and works well with Vue. Next, I will introduce myself to use AXIOS configuration in the project to complete the global loading state processing

Store status record

index.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    // Whether it is in the request
    isAppending: false
  },
  mutations: { changeAppending(state, bool) { state.isAppending = bool; }}});Copy the code

Axios configuration

axios/index.js

/** * axios configuration */
import axios from "axios";
import qs from "qs";
// Import a VUEX entry file to record the loading state
import store from ".. /store/store";

// Timer array. Generally, we wait for more than one second before loading. If the loading state is prompted at the beginning, the user experience is not very good
let timers = [],
  timer = null;

const service = axios.create({
  // Set the timeout period
  timeout: 60000.baseURL: process.env.VUE_APP_BASE_URL
});

/* * For post requests, we need a request header, so we can set the default * * for post to application/x-www-form-urlencoded; charset=UTF-8 */
service.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded; charset=UTF-8";

// Intercept the request
service.interceptors.request.use(
  config= > {
    // How to configure formData
    config.data = qs.stringify(config.data);
    // Start the delay timer before each request, and record it in the array, so that it can be cleared after the response comes back
    timer = setTimeout((a)= > {
      !store.state.isAppending && store.commit("changeAppending".true);
    }, 1000);
    timers.push(timer);
    return config;
  },
  error => {
    // ...
    return Promise.reject(error); });// Intercept the response
service.interceptors.response.use(
  response= > {
    // Please remove all timers;
    clearAllTimer();
    // Remove the loading effect
    store.commit("changeAppending".false);
    return response;
  },
  error => {
    clearAllTimer();
    store.commit("changeAppending".false);
    return Promise.reject(error); });function clearAllTimer() {
  timers.forEach(item= > {
    clearTimeout(item);
  });
  timers = [];
}

export default service;
Copy the code

Used in vUE projects

In my project, THE UI component library —- Vant of VUE is applied, and the Toast component provided by it can be used to complete the interaction of loading state.

Use main.js

import Vue from "vue";
// Introduce Toast on demand
import { Toast } from "vant";
import App from "./App.vue";
import router from "./router/index";
import axios from "./axios/index";
import store from "./store/store";
import "./common/less/reset.less";

/ / register
Vue.use(Toast);
Vue.config.productionTip = false;
Vue.prototype.$axios = axios;
// runtimex
new Vue({
  router,
  store,
  render: h= > h(App)
}).$mount("#app");
Copy the code

Finally, we listen for isAppending status in the project root component app.vue

<template> <div id="app"> <router-view /> </div> </template> <script> import { mapState } from "vuex"; export default { name: "App", data() { return {}; }, computed: { ... mapState(["isAppending"]) }, watch: { isAppending(val) { console.log("isApending", val); val ? This.$toast.loading({message: "loading...") , duration: 0, forbidClick: true }) : this.$toast.clear(); } }, created() {}, methods: {} }; </script> <style lang="less"> @import "./common/less/reset.less"; </style>Copy the code

And you’re done!