vue前端頁(yè)面數(shù)據(jù)加載添加loading效果的實(shí)現(xiàn)
前端頁(yè)面數(shù)據(jù)加載添加loading效果
在前端上傳文件或者加載數(shù)據(jù)的時(shí)候會(huì)有一段等待時(shí)間,如果加上一個(gè)loading效果會(huì)減輕用戶等待的枯燥,這里就來(lái)記錄學(xué)習(xí)一下如何實(shí)現(xiàn)loading效果。

效果大致如下,樣式我們是可以自定義的。
具體實(shí)現(xiàn)
let thisContent = this;
let loading = thisContent.$loading({
lock: true,
text: '上傳中,請(qǐng)稍候...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.5)'
})
// 中間進(jìn)行一系列的操作
// 上傳成功后關(guān)閉loading, 并顯示上傳成功
loading.close();
thisC.$message('上傳文件成功');
這樣一個(gè)簡(jiǎn)單的loading效果就實(shí)現(xiàn)了。
全局loading配置
請(qǐng)求的時(shí)候 需要一個(gè)全局loading來(lái)攔截 若是頁(yè)面單獨(dú)引用的話 就有點(diǎn)繁瑣了 所以需要再全局封裝一個(gè) 此時(shí)就要明白 再哪里封裝了 先考慮一下 為什么要用
一方面是為了防止重復(fù)操作
另一方面是為了一個(gè)加載的效果能夠更明顯
所以 再請(qǐng)求的時(shí)候加 就能聯(lián)想到axios攔截器的位置處理了 話不多說(shuō) 開(kāi)始擼代碼 全程copy就行了
1 再src/componennts/Spinner下面建立一個(gè)index.vue
<template>
<div class="loading-page bg-opacity" :style="{display:hide?'none':'block'}">
<div class="dark" @dblclick="close">
<div class="la-ball-spin-clockwise la-2x">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
hide: true
}
},
methods: {
close() {
document.querySelector('.loading-page').style.display = 'none';
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.show {
display: block;
}
.hide {
display: none;
}
.loading-page {
background: rgba(0, 0, 0, .65);
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-height: 100%;
min-width: 100%;
transition: all 1s;
z-index: 20000;
&.hide {
display: none;
}
&.bg-opacity {
background: rgba(0, 0, 0, 0);
}
.dark {
width: 100px;
height: 100px;
border-radius: 10px;
background: rgba(0, 0, 0, .65);
position: absolute;
top: 40%;
left: 50%;
margin-left: -50px;
text-align: center;
img {
width: 70px;
height: 70px;
margin-top: 15px;
}
}
}
.la-ball-spin-clockwise{
width: 64px;
height: 64px;
margin-top: 18px;
margin-left: 18px;
display: block;
font-size: 0;
color: #fff;
position: relative;
box-sizing: border-box;
animation-play-state: running;
}
.la-ball-spin-clockwise>div{
width: 16px;
height: 16px;
margin-top: -8px;
margin-left: -8px;
position: absolute;
border-radius: 100%;
animation: ball-spin-clockwise 1s infinite ease-in-out;
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor;
animation-play-state: running;
}
.la-ball-spin-clockwise>div:nth-child(1){
top: 5%;
left: 50%;
webkit-animation-delay: -.875s;
-moz-animation-delay: -.875s;
-o-animation-delay: -.875s;
animation-delay: -.875s;
}
.la-ball-spin-clockwise>div:nth-child(2) {
top: 18.1801948466%;
left: 81.8198051534%;
-webkit-animation-delay: -.75s;
-moz-animation-delay: -.75s;
-o-animation-delay: -.75s;
animation-delay: -.75s;
}
.la-ball-spin-clockwise>div:nth-child(3) {
top: 50%;
left: 95%;
-webkit-animation-delay: -.625s;
-moz-animation-delay: -.625s;
-o-animation-delay: -.625s;
animation-delay: -.625s;
}
.la-ball-spin-clockwise>div:nth-child(4) {
top: 81.8198051534%;
left: 81.8198051534%;
-webkit-animation-delay: -.5s;
-moz-animation-delay: -.5s;
-o-animation-delay: -.5s;
animation-delay: -.5s;
}
.la-ball-spin-clockwise>div:nth-child(5) {
top: 94.9999999966%;
left: 50.0000000005%;
-webkit-animation-delay: -.375s;
-moz-animation-delay: -.375s;
-o-animation-delay: -.375s;
animation-delay: -.375s;
}
.la-ball-spin-clockwise>div:nth-child(6) {
top: 81.8198046966%;
left: 18.1801949248%;
-webkit-animation-delay: -.25s;
-moz-animation-delay: -.25s;
-o-animation-delay: -.25s;
animation-delay: -.25s;
}
.la-ball-spin-clockwise>div:nth-child(7) {
top: 49.9999750815%;
left: 5.0000051215%;
-webkit-animation-delay: -.125s;
-moz-animation-delay: -.125s;
-o-animation-delay: -.125s;
animation-delay: -.125s;
}
.la-ball-spin-clockwise>div:nth-child(8) {
top: 18.179464974%;
left: 18.1803700518%;
-webkit-animation-delay: 0s;
-moz-animation-delay: 0s;
-o-animation-delay: 0s;
animation-delay: 0s;
}
@-webkit-keyframes ball-spin-clockwise{
0%,100%{
opacity:1;
-webkit-transform:scale(1);
transform:scale(1)}
20%{
opacity:1
}
80%{
opacity:0;
-webkit-transform:scale(0);
transform:scale(0)
}
}
@-moz-keyframes ball-spin-clockwise{
0%,100%{
opacity:1;
-moz-transform:scale(1);
transform:scale(1)
}
20%{
opacity:1
}
80%{
opacity:0;
-moz-transform:scale(0);
transform:scale(0)
}
}
@-o-keyframes ball-spin-clockwise{
0%,100%{
opacity:1;
-o-transform:scale(1);
transform:scale(1)
}
20%{
opacity:1
}
80%{
opacity:0;
-o-transform:scale(0);
transform:scale(0)
}
}
@keyframes ball-spin-clockwise{
0%,100%{
opacity:1;
-webkit-transform:scale(1);
-moz-transform:scale(1);
-o-transform:scale(1);
transform:scale(1)
}
20%{
opacity:1
}
80%{
opacity:0;
-webkit-transform:scale(0);
-moz-transform:scale(0);
-o-transform:scale(0);transform:scale(0)
}
}
</style>2 再u(mài)tils下面tools.js
class Msg {
static loading() {
document.querySelector('.loading-page').style.display = 'block';
}
static hideLoading() {
document.querySelector('.loading-page').style.display = 'none';
}
}
export {
Tools,
Msg
}3 再u(mài)tils下面建議一個(gè)request.js 封裝的axios請(qǐng)求
import axios from 'axios'
import qs from 'qs'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import router from '@/router'
import {Msg} from '@/utils/tools';
import { removeToken } from '@/utils/auth'
var allResquest = 0;
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url
withCredentials: true, // 跨域請(qǐng)求時(shí)發(fā)送 cookies
paramsSerializer: params => { // 查詢字符串中的數(shù)組不使用方括號(hào)
return qs.stringify(params, { indices: false })
},
timeout: 15000 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['Authorization'] = 'Bearer ' + getToken()
config.headers['filterMode'] = localStorage.getItem('dataType')
}
config.headers['project'] = "csr"
allResquest = allResquest + 1;
if (config.mask !== true) {
Msg.loading()
}
return config
},
error => {
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get information such as headers or status
* Please return response => response
*/
/**
* 下面的注釋為通過(guò)在response里,自定義code來(lái)標(biāo)示請(qǐng)求狀態(tài)
* 當(dāng)code返回如下情況則說(shuō)明權(quán)限有問(wèn)題,登出并返回到登錄頁(yè)
* 如想通過(guò) XMLHttpRequest 來(lái)狀態(tài)碼標(biāo)識(shí) 邏輯可寫(xiě)在下面error中
* 以下代碼均為樣例,請(qǐng)結(jié)合自生需求加以修改,若不需要,則可刪除
*/
response => {
allResquest = allResquest - 1;
const res = response.data;
if (response.status === 200) {
if (allResquest === 0) {
Msg.hideLoading();
}
// 50008 系統(tǒng)無(wú)此賬號(hào)
// 50010 賬號(hào)禁用
// 50012 賬號(hào)或密碼錯(cuò)誤
// 50013 主賬號(hào)被禁用,禁止登錄
// 50014 token失效
// 50015 登錄失敗,無(wú)操作權(quán)限,請(qǐng)聯(lián)系系統(tǒng)管理員!
// 50016 驗(yàn)證碼錯(cuò)誤
// 429 限流 服務(wù)器擁擠,請(qǐng)稍后再試
// -999 未知錯(cuò)誤
// 403 無(wú)權(quán)限
if (res.code === 50008 || res.code === 50010 || res.code === 50012 || res.code === 50013 ||
res.code === 50016 || res.code === 50015 || res.code === 429 || res.code === -999 || res.code === 403 || res.code === 500) {
Message({
message: res.msg || 'error',
type: 'error',
duration: 5 * 1000,
offset: 0
})
return Promise.reject(res.msg || 'error')
} else if (res.code === 50014) {
if (store.getters.token) {
removeToken()
}
MessageBox.alert( res.msg,'錯(cuò)誤提示', {
confirmButtonText: '確定',
callback: action => {
store.dispatch('logout')
router.push(`/login`)
}
})
return false
}
return res
}
},
error => {
allResquest = allResquest - 1;
Msg.hideLoading();
Message({
message: '服務(wù)擁擠,請(qǐng)稍后重試!',
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service4 修改app.vue
<template> ? <div id="app"> ? ? <router-view /> ? ? <Spinner></Spinner> ? </div> </template>
<script>
import Spinner from '@/components/Spinner'
export default {
? name: 'App',
? components: {
? ? Spinner
? }
}
</script><style> </style>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Vue實(shí)現(xiàn)上拉加載下一頁(yè)效果的示例代碼
- vue實(shí)現(xiàn)滑動(dòng)到底部加載更多效果
- vue實(shí)現(xiàn)頁(yè)面加載動(dòng)畫(huà)效果
- Vue ElementUI this.$confirm async await封裝方式
- vue+el使用this.$confirm,不能阻斷代碼往下執(zhí)行的解決
- Vue+Element-ui彈窗?this.$alert?is?not?a?function問(wèn)題
- Vue給?elementUI?中的?this.$confirm、this.$alert、?this.$prompt添加按鈕加載效果
相關(guān)文章
Vue設(shè)置提示和警告彈出框?qū)崙?zhàn)案例
頁(yè)面中會(huì)有很多時(shí)候需要彈窗提示,下面這篇文章主要給大家介紹了關(guān)于Vue設(shè)置提示和警告彈出框的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
Vue?實(shí)現(xiàn)接口進(jìn)度條示例詳解
這篇文章主要介紹了Vue實(shí)現(xiàn)接口進(jìn)度條功能,在請(qǐng)求數(shù)據(jù)的過(guò)程中,需要添加監(jiān)聽(tīng)函數(shù)來(lái)監(jiān)測(cè)數(shù)據(jù)請(qǐng)求的過(guò)程變化,并更新組件相應(yīng)的屬性和界面元素,本文結(jié)合實(shí)例代碼詳細(xì)講解,需要的朋友可以參考下2023-04-04
Vue.$set 失效的坑 問(wèn)題發(fā)現(xiàn)及解決方案
這篇文章主要介紹了Vue.$set 失效的坑 問(wèn)題發(fā)現(xiàn)及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
vue-model實(shí)現(xiàn)簡(jiǎn)易計(jì)算器
這篇文章主要為大家詳細(xì)介紹了vue-model實(shí)現(xiàn)簡(jiǎn)易計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
vue生成二維碼QR?Code的簡(jiǎn)單實(shí)現(xiàn)方法示例
這篇文章主要為大家介紹了vue生成二維碼QR?Code的實(shí)現(xiàn)示例詳情,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
vue跳轉(zhuǎn)頁(yè)面打開(kāi)新窗口,并攜帶與接收參數(shù)方式
這篇文章主要介紹了vue跳轉(zhuǎn)頁(yè)面打開(kāi)新窗口,并攜帶與接收參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
一文詳解Vue中如何實(shí)現(xiàn)頁(yè)面骨架屏
為了提升頁(yè)面加載速度,我們可以使用頁(yè)面骨架屏技術(shù)來(lái)優(yōu)化用戶感知,下面就跟隨小編一起學(xué)習(xí)一下如何在vue中實(shí)現(xiàn)頁(yè)面骨架屏吧2024-03-03

