【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果

文章目录

    • 目标
    • 过程与代码
      • loading效果
      • mainStore控制loading显示
      • 点击蒙板取消网络请求
      • 在网络请求处添加对loading的控制
    • 效果
    • 总代码
      • 修改或添加的文件
      • loading.vue
      • service/request/index
      • store/modules/main
      • App.vue
    • 参考

本项目博客总结:【前端】Vue项目:旅游App-博客总结

目标

在发送网络请求的时候显示loading:

【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果_第1张图片

过程与代码

loading效果

本App中任何一个地方发送网络请求都要显示loading效果,因此我们要把它封装在一个组件中。且在App.vue中引入。

css代码解释,此做法可以:

  • 让明确宽高的盒子垂直水平居中
  • 让无宽高的盒子填满父容器
  • 这里是第二种
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;

loading总代码:

<template>
    <div class="loading">
        <div class="bg">
            <img src="@/assets/img/home/full-screen-loading.gif" alt="">
        div>
    div>
template>

<script setup>

script>

<style lang="less" scoped>
.loading {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;

    // 蒙板颜色
    background-color: rgba(0, 0, 0, .2);

    // loading的效果会在任何效果之上
    z-index: 999;

    // 垂直水平居中
    display: flex;
    justify-content: center;
    align-items: center;

    .bg {
        background: url(@/assets/img/home/loading-bg.png) 0 0 /100% 100%;
        width: 104px;
        height: 104px;

        display: flex;
        justify-content: center;
        align-items: center;

        img {
            width: 70px;
            height: 70px;
            margin-bottom: 9px;
        }
    }

}
style>

效果:背景有点灰色的地方就是蒙板

【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果_第2张图片

mainStore控制loading显示

我们的需求:在发送网络请求(简单来说就是加载数据)的时候显示loading。这样更加用户友好。

显然,App中很多页面都有可能要加载数据,因此我们需要把loading显示的控制放在一个地方统一管理。不难想到要放到store的mainStore中管理(上篇管理整个App时间设置的地方)。

useMainStore:

isLoading:false

html:

<div class="loading" v-if="mainStore.isLoading">

js:

import useMainStore from '../../store/modules/main';

const mainStore=useMainStore()

点击蒙板取消网络请求

这是一个常见的效果。

html:

<div class="loading" v-if="mainStore.isLoading" @click="loadingClick()">

js:

function loadingClick() {
    mainStore.isLoading = false
}

在网络请求处添加对loading的控制

我们的需求:在发送网络请求的时候显示loading。

而我们在代码中封装了网络请求的功能,很显然,我们可以在request中添加在对loading的控制,如:

request(config) {
 loadingStore.changeLoading(true);
 mainStore.isLoading = true
 return new Promise((resolve, reject) => {
   this.instance
     .request(config)
     .then((res) => {
       resolve(res.data);
       mainStore.isLoading = false
     })
     .catch((err) => {
       console.log("request err:", err);
       reject(err);
       mainStore.isLoading = false
     })
     .finally(() => {
       loadingStore.changeLoading(false);
     });
 });

【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果_第3张图片
在发送请求时显示loading,发送完或发送完都取消显示。

但是不推荐这样做,我们希望一个方法只做一个功能。这里推荐使用拦截器

拦截器 | Axios 中文文档 | Axios 中文网 (axios-http.cn)
axios 请求拦截器&响应拦截器 - 简书 (jianshu.com)

注意,拦截器是绑定在实例上的。我们要把它写在构造函数里。

constructor(baseURL) {
  this.instance = axios.create({
    baseURL,
    timeout: TIMEOUT,
  });

  this.instance.interceptors.request.use(config => {
    // 发送网络请求前要做的事
    mainStore.isLoading = true
    return config
  }, err => {
    // 发送网络请求失败要做的事
    return err
  })

  this.instance.interceptors.response.use(res => {
    // 响应成功要做的事
    mainStore.isLoading = false
    return res
  }, err => {
    // 响应失败要做的事
    mainStore.isLoading = false
    return err
  })
}

效果

发送网络请求时会显示loading,数据加载完后就消失。

总代码

修改或添加的文件

【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果_第4张图片

loading.vue

loading组件。

<template>
    <div class="loading" v-if="mainStore.isLoading" @click="loadingClick()">
        <div class="bg">
            <img src="@/assets/img/home/full-screen-loading.gif" alt="">
        div>
    div>
template>

<script setup>
import useMainStore from '../../store/modules/main';

const mainStore = useMainStore()

function loadingClick() {
    mainStore.isLoading = false
}
script>

<style lang="less" scoped>
.loading {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;

    // 蒙板颜色
    background-color: rgba(0, 0, 0, .2);

    // loading的效果会在任何效果之上
    z-index: 999;

    // 垂直水平居中
    display: flex;
    justify-content: center;
    align-items: center;

    .bg {
        background: url(@/assets/img/home/loading-bg.png) 0 0 /100% 100%;
        width: 104px;
        height: 104px;

        display: flex;
        justify-content: center;
        align-items: center;

        img {
            width: 70px;
            height: 70px;
            margin-bottom: 9px;
        }
    }

}
style>

service/request/index

在网络请求的代码中添加请求拦截器和响应拦截器。

import axios from "axios";

import { useLoadingStore } from "@/store/modules/loading";
import useMainStore from "../../store/modules/main";
import { baseURL, TIMEOUT } from "./config";

const loadingStore = useLoadingStore();
const mainStore = useMainStore()

class HYRequest {
  constructor(baseURL) {
    this.instance = axios.create({
      baseURL,
      timeout: TIMEOUT,
    });

    this.instance.interceptors.request.use(config => {
      // 发送网络请求前要做的事
      mainStore.isLoading = true
      return config
    }, err => {
      // 发送网络请求失败要做的事
      return err
    })

    this.instance.interceptors.response.use(res => {
      // 响应成功要做的事
      mainStore.isLoading = false
      return res
    }, err => {
      // 响应失败要做的事
      mainStore.isLoading = false
      return err
    })
  }

  request(config) {
    loadingStore.changeLoading(true);
    return new Promise((resolve, reject) => {
      this.instance
        .request(config)
        .then((res) => {
          resolve(res.data);
        })
        .catch((err) => {
          console.log("request err:", err);
          reject(err);
        })
        .finally(() => {
          loadingStore.changeLoading(false);
        });
    });
  }

  get(config) {
    return this.request({ ...config, method: "get" });
  }

  post(config) {
    return this.request({ ...config, method: "post" });
  }
}

export default new HYRequest(baseURL);

store/modules/main

添加isLoading来控制loading的显示。

import { defineStore } from "pinia"

const startDay = new Date()
const endDay = new Date()
endDay.setDate(startDay.getDate() + 1)

const useMainStore = defineStore('main', {
    state: () => ({
        token:'',

        startDay:startDay,
        endDay:endDay,

        isLoading:false,
    }),
    actions: {

    }
})

export default useMainStore

App.vue

添加loading组件。

<template>
    <div class="app">
        <router-view/>
        <tab-bar v-if="!$route.meta.hideTabBar">tab-bar>
        <loading/>
    div>
template>

<script setup>

import tabBar from './components/tab-bar/tab-bar.vue';
import loading from './components/loading/loading.vue';

import { useRoute } from 'vue-router'

const route=useRoute()

script>

<style lang="less" scoped>

style>

【前端】Vue项目:旅游App-(19)loading:网络请求时显示loading效果_第5张图片

参考

css中 top, right, bottom, left设置为0有什么用?它和width:100%和height:100%有什么区别?

CSS Backgrounds(背景) | 菜鸟教程 (runoob.com)

拦截器 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

axios 请求拦截器&响应拦截器 - 简书 (jianshu.com)

你可能感兴趣的:(前端案例,前端,vue.js,旅游)