前端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-(23)detail:房东介绍热门评论预定须知组件