首先说一下我用的loading是一个第三方json动画库,底层用了window和document对象,在服务端会报错,只能在客户端跑。所以在服务端运行的请求钩子是不能进行loading效果的
先引入第三方动画库lottiefiles
import '@lottiefiles/lottie-player'
- 在nuxt.config.js中的plugins模块中引入
module.exports = {
plugins: [
{ src: '~/plugins/Loading/lottiePlayer.js', ssr: false },
],
}
在plugins/Loading下创建一个loading.vue,并挂载到Vue实例原型上
<template>
<div v-show="loading" class="loading-page">
<lottie-player
v-show="isShow"
class="lottie"
src="https://assets8.lottiefiles.com/packages/lf20_nm1huacl.json"
background="transparent"
speed="1.5"
style="width: 300px; height: 300px"
loop
autoplay
/>
<lottie-player
v-show="!isShow"
class="lottie"
src="https://assets4.lottiefiles.com/private_files/lf30_weidduaf.json"
background="transparent"
speed="1"
style="width: 300px; height: 300px"
loop
autoplay
/>
</div>
</template>
<script>
export default {
data: () => ({
loading: false,
isShow: Math.floor(Math.random() * 2)
})
}
</script>
<style lang="less" scoped>
.loading-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
overflow: hidden;
z-index: 99999;
.lottie {
position: absolute;
top: 47%;
left: 51%;
transform: translate(-51%, -47%);
}
&::before {
position: absolute;
content: "";
width: 100%;
height: 100%;
background: rgba(235, 235, 235, 0.8);
backdrop-filter: blur(5px);
filter: Alpha(Opacity=90);
opacity: 0.9;
}
}
</style>
import Vue from 'vue'
import Loading from './loading.vue'
let instance = null
const loading = {
install(Vue) {
if (!instance) {
const MyLoading = Vue.extend(Loading)
instance = new MyLoading({
el: document.createElement('div')
})
document.body.appendChild(instance.$el)
}
instance.loading = false
const customMethods = {
start() {
instance.loading = true
},
finish() {
instance.loading = false
}
}
if (!Vue.$loading) {
Vue.$loading = customMethods
Vue.prototype.$loading = Vue.$loading
} else {
console.log('$loading方法被占用')
}
}
}
Vue.use(loading)
- 然后在nuxt.config.js中的plugins注册一下,注意:要取消nuxt原来的loading效果,因为它原来在
n
u
x
t
挂
载
的
也
是
nuxt挂载的也是
nuxt挂载的也是loading
export default {
loading: false,
plugins: [
{ src: '~/plugins/Loading/lottiePlayer.js', ssr: false },
{ src: '~/plugins/Loading/index.js', ssr: false },
],
}
在axios拦截器中添加loading
import Vue from 'vue'
import {
message
} from 'ant-design-vue'
export default ({ store, route, redirect, $axios, req }) => {
$axios.onRequest(config => {
if (process.client) {
Vue.prototype.$loading.start()
}
const accessToken = store.state.accessToken
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken.replace(/"/g, '')}`
}
return config
})
$axios.onResponse(res => {
if (process.client) {
console.log('客户端拦截数据:', res.data)
setTimeout(() => {
Vue.prototype.$loading.finish()
}, 300)
}
if ((res.status !== 200 || res.data.code !== 20000) && process.client) {
message.error(res.message || res.data.message || '数据响应异常', 1)
}
if (res?.data.code !== 20000 && process.server) {
console.error('服务端:', res?.data.message || '数据响应异常')
console.error('服务端错误数据:', res.data)
}
return res.data
})
$axios.onError(error => {
if (process.client) {
Vue.prototype.$loading.finish()
}
const { response: res } = error
if (res.status === 401 && res.data.code === 1401) {
let isLock = true
if (isLock && store.state.refreshToken) {
isLock = false
redirect(`${process.env.authURL}/refresh?redirectURL=${redirectURL(route, req)}`)
} else {
isLock = true
store.commit('RESET_USER_STATE')
redirect(`${process.env.authURL}?redirectURL=${redirectURL(route, req)}`)
}
message.error(res.data.message, 1)
if (process.client) {
Vue.prototype.$loading.start()
}
return Promise.reject(res.data.message || 'Error')
}
message.error(res.data.message, 1)
return Promise.reject('令牌过期,重新登录')
})
}
const redirectURL = (route, req) => {
if (process.client) {
return window.location.href
}
return `${process.env.NODE_ENV === 'production' ? 'https://' : 'http://'}` + req.headers.host + route.fullPath
}
加载数据效果(在客户端请求数据时生效) 各位老板点赞三连
更多推荐:wantLG的《普歌-实测Nuxt坑,配置@nuxt/axios、拦截器、代理跨域,请求》
|