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

Posted karshey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端Vue项目:旅游App-(19)loading:网络请求时显示loading效果相关的知识,希望对你有一定的参考价值。

文章目录

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

目标

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

过程与代码

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>

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

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);
     );
 );


在发送请求时显示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,数据加载完后就消失。

总代码

修改或添加的文件

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>

参考

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

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

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

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

以上是关于前端Vue项目:旅游App-(19)loading:网络请求时显示loading效果的主要内容,如果未能解决你的问题,请参考以下文章

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

前端Vue项目:旅游App-(25):移动端适配

前端Vue项目:旅游App-(23)detail:房东介绍热门评论预定须知组件

前端Vue项目:旅游App-(22)detail:房屋信息房屋设施插槽

前端Vue项目:旅游App-NavBar:结构与样式

前端Vue项目:旅游App-(24)useScroll:加强useScroll的功能性,监听窗口和页面的滚动