This is the 11th day of my participation in Gwen Challenge.

Introduction to 👽

Loading is an essential component in every project. It can not only improve user waiting experience, but also prevent misoperation and prevent events from shaking. There are many forms of Loading, such as intra-component Loading, button Loading and global Loading.

Global loading is usually accompanied by asynchronous requests: Loaidng is displayed at the beginning of the request, and loading disappears at the end of the request. With this basic requirement in mind, let’s encapsulate a request-based global loading.

👽 Component Preparation

Let’s start with our loading component, which is no different from custom components. There are two main points at this stage:

1. Use not-allowed to prevent event penetration. 2. Component styles must be high enough so that they do not cover all elements;Copy the code
<! --index.vue-->
<template>
  <div class="global-box">
    <div class="wrap">
      <div class="loading">
        <div class="bounceball"></div>
        <div class="text">LOADING</div>
      </div>
    </div>
  </div>
</template>
<script>
export default {};
</script>

<style lang="less" scoped>
@import './index.less';
</style>
Copy the code
//index.less
@width: 15px;
@height: 15px;

@bounce_height: 30px;

.global-box {
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0.0.0.0.3);
  cursor: not-allowed;
}

.wrap {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.text {
  display: inline-block;
  margin-left: 5px;
  color: #ff4600;
}

.bounceball {
  display: inline-block;
  position: relative;
  margin-right: 10px;
  width: @width;
  height: 37px;

  &::before {
    display: block;
    position: absolute;
    top: 0;
    border-radius: 50%;
    width: @width;
    height: @height;
    background-color: #ff4600;
    transform-origin: 50%;
    animation: bounce 500ms alternate infinite ease;
    content: ' '; }}@keyframes bounce {
  0% {
    top: @bounce_height;
    border-radius: 60px 60px 20px 20px;
    height: 5px;
    transform: scaleX(2);
  }

  35% {
    border-radius: 50%;
    height: @height;
    transform: scaleX(1);
  }

  100% {
    top: 0; }}Copy the code

You can mount it directly on the page as a component and see what it looks like:

👽 Mount plug-ins

Mounting plug-ins is the key to this encapsulation process. The general idea in this process is:

Enable Loading to mount the Loading plug-in to the page. To disable Loading, you can uninstall the Loading plug-in from the page.Copy the code

The truth is very simple, directly on the practice.

//mountLoading.js
import Vue from 'vue';
import Loading from './index';

const LoadingConstructor = Vue.extend(Loading);// Define the constructor for Loading

const LoadingInstance = new LoadingConstructor({
  el: document.createElement('div')});// Create an instance

const loading = {
  show() {
    // Display method: mount instance to body
    document.body.appendChild(LoadingInstance.$el);
  },
  hide() {
    // Hide methods: write from the body in the instance
    document.body.removeChild(LoadingInstance.$el); }};// Create the Loading plug-in
export default {
   The install method must be provided when the plug-in is an object
  install() {
    / / binding $loading! Vue.$loading && (Vue.$loading = loading);// global mixin
    Vue.mixin({
      created() {
        this.$loading = Vue.$loading; }}); }};Copy the code
//main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';

import Loading from './loading/mountLoading';

Vue.use(Loading); // Use the loading plug-in

Vue.config.productionTip = false;
new Vue({
  router,
  render: (h) = > h(App),
}).$mount('#app');

Copy the code

In this case, the loading plug-in is successfully mounted. Run this.$loading.show() or this.$loading.hide() to change the loading state.

👽 Request follow

This step takes advantage of axios’ interceptor, and the general idea is:

Loading is enabled in the request interceptor; Turn off loading in response interceptor.Copy the code
//request.js

import axios from 'axios';
import Vue from 'vue';

const instance = axios.create({
  baseURL,
  timeout: 30000});// Request interceptor
instance.interceptors.request.use((config) = > {
  Vue.$loading.show();

  return config;
});

// Response interceptor
instance.interceptors.response.use(
  (res) = > {
    Vue.$loading.hide();
    return res;
  },
  (err) = > {
    console.log('err: ', err); Vue.$loading.hide(); });export default instance;
Copy the code

👽 epilogue

Iron juice people, did you learn 👻?