今日心情一般,效率不高撒
关于路由函数的使用可以去下文看哦!!非常全
一.先说结论,用loading还是骨架屏?
测试了一下loading和骨架屏在时耗上并没有多少区别,具体的使用还是要结合用户体验考虑,
在从A页面切换到B页面时,用户未访问过B页面,使用骨架屏可以给用户预先了解页面框架,提升用户体验
在从A页面切换到A页面时,但是携带了不同数据,存在一个数据刷新的问题,我考虑的是为避免网络差,请求时间过长,骨架屏带给用户的一种宕机的感觉,因为这个时候用户已经见过框架了,所以直接用loading就可以
当然具体用什么,听产品的!!!
二.在什么时候请求获得新数据呢,开或关骨架屏和loading?
1.尽可能早的接受传参并更块的触发请求函数能够更快得到数据
Vue 路由导航守卫(全局守卫、路由独享守卫、组件内守卫)详解_离开页面时移除全局前置守卫(beforeeach守卫-优快云博客
beforeRouteEnter函数是在setup前!(要写在setup函数外边)
beforeRouteUpdate函数指组件是非首次进入触发,不会再触发created和mounted
在这两个函数中触发请求函数
2.页面的跳转有两种情况:
①.从A页面跳转到test页面下,页面经过:
离开A页面 --》(beforeRouteEnter )骨架屏 --》数据请求完成并重新渲染
②.从test页面到test页面,只是更新了参数信息,页面经过:
test页面老数据 --》(beforeRouteUpdate)loadiing --》test页面新数据
三.在函数中的处理:开骨架屏(开loading)--》请求数据--》关骨架屏(关loading)
代码如下,用延时函数来模仿请求数据,说几个注意点
①.骨架屏的使用,在初始无数据的时候,可以先估计可视页面有多少个item项来准备骨架屏,如果你要在非首次进入页面时使用骨架屏,为了不根据旧数据生成骨架屏,要先对数据进行初始化处理,具体看我备注那段要看更新数据骨架屏效果,函数换为备注那段即可,html需要稍加修改
②.注意骨架屏或loading的开关,在请求数据到得到数据的前后
③.代码不用看太细,因为是前台数据,所以加了些处理,向后台请求数据的时候没有这么乱
<script>
import { ref, onMounted } from 'vue'
import { onBeforeRouteUpdate } from 'vue-router'
import { useRouter } from 'vue-router'
const LIST_INFO = [
{
name: 'QQ',
describe: 'QQ是腾讯公司推出的一款即时通讯软件',
},
{
name: '微信',
describe: '微信是腾讯公司推出的一款即时通讯软件',
},
{
name: '钉钉',
describe: '钉钉是阿里巴巴推出的一款即时通讯软件',
},
{
name: '飞书',
describe: '飞书是字节跳动推出的一款即时通讯软件',
},
{
name: '企业微信',
describe: '企业微信是腾讯公司推出的一款即时通讯软件',
},
{
name: 'TIM',
describe: 'TIM是腾讯公司推出的一款即时通讯软件',
},
{
name: 'QQ邮箱',
describe: 'QQ邮箱是腾讯公司推出的一款邮箱软件',
},
]
const LIST_INFO1 = [
{
name: 'QQ',
describe: 'QQ是腾讯公司推出的一款即时通讯软件',
},
{
name: '微信',
describe: '微信是腾讯公司推出的一款即时通讯软件',
},
{
name: '钉钉',
describe: '钉钉是阿里巴巴推出的一款即时通讯软件',
},
{
name: '飞书',
describe: '飞书是字节跳动推出的一款即时通讯软件',
},
{
name: '企业微信',
describe: '企业微信是腾讯公司推出的一款即时通讯软件',
},
{
name: 'TIM',
describe: 'TIM是腾讯公司推出的一款即时通讯软件',
},
{
name: 'QQ邮箱',
describe: 'QQ邮箱是腾讯公司推出的一款邮箱软件',
},
{
name: '网易邮箱',
describe: '网易邮箱是网易公司推出的一款邮箱软件',
},
{
name: '新浪邮箱',
describe: '新浪邮箱是新浪公司推出的一款邮箱软件',
},
{
name: '搜狐邮箱',
describe: '搜狐邮箱是搜狐公司推出的一款邮箱软件',
},
{
name: '139邮箱',
describe: '139邮箱是中国移动推出的一款邮箱软件',
},
{
name: '163邮箱',
describe: '163邮箱是网易公司推出的一款邮箱软件',
},
{
name: '126邮箱',
describe: '126邮箱是网易公司推出的一款邮箱软件',
},
{
name: 'QQ音乐',
describe: 'QQ音乐是腾讯公司推出的一款音乐软件',
},
{
name: '网易云音乐',
describe: '网易云音乐是网易公司推出的一款音乐软件',
},
{
name: '酷狗音乐',
describe: '酷狗音乐是酷狗公司推出的一款音乐软件',
},
]
export default {
beforeRouteEnter(to, from, next) {
console.log('首次进入组件')
next((vm) => {
vm.skeletonLoading = true // 更新 skeletonLoading 状态
setTimeout(() => {
// 在url有参数的情况下优先展示参数对应的数据
vm.data = to.query.list_Info ? JSON.parse(to.query.list_Info) : LIST_INFO
// console.log('data.value', vm.data)
vm.skeletonLoading = false // 更新 skeletonLoading 状态
}, 2000)
})
},
created() {
console.log('created')
},
setup() {
const data = ref(20)
const skeletonLoading = ref(true) // 初始化为 true
const loading = ref(false) // 初始化为 true
const router = useRouter()
onBeforeRouteUpdate((to) => {
console.log('再次进入组件')
loading.value = true // 更新 loading 状态
setTimeout(() => {
try {
data.value = JSON.parse(to.query.list_Info)
// console.log('data.value', data.value)
loading.value = false // 更新 loading 状态
} catch {
//当二次进入页面后,也就是url会有query参数,这个时候点击回退,url会变成首次进入的状态就是没有query参数,因为这次回退本质上是再次进入组件,执行onBeforeRouteUpdate函数,to.query.list_Info数据没有一次会报错,导致loading状态一直为true,所以要抛出异常,更改data和loading,如果是正常情况的话首次进入这个页面,也是会有参数的
setTimeout(() => {
data.value = LIST_INFO
loading.value = false // 更新 loading 状态
}, 2000)
}
}, 2000)
})
// onBeforeRouteUpdate((to) => {
// console.log('再次进入组件')
// data.value = 20
// skeletonLoading.value = true // 更新 loading 状态
// setTimeout(() => {
// try {
// data.value = JSON.parse(to.query.list_Info)
// console.log('data.value', data.value)
// skeletonLoading.value = false // 更新 loading 状态
// } catch {
// //当二次进入页面后,也就是url会有query参数,这个时候点击回退,url会变成首次进入的状态就是没有query参数,因为这次回退本质上是再次进入组件,执行onBeforeRouteUpdate函数,to.query.list_Info数据没有一次会报错,导致loading状态一直为true,所以要抛出异常,更改data和loading,如果是正常情况的话首次进入这个页面,也是会有参数的
// setTimeout(() => {
// data.value = LIST_INFO
// skeletonLoading.value = false // 更新 loading 状态
// }, 2000)
// }
// }, 2000)
// })
const handleGetMoreInfo = () => {
console.log(LIST_INFO1)
router.push({
path: '/test',
query: { list_Info: JSON.stringify(LIST_INFO1) },
})
}
onMounted(() => {
console.log('mounted')
})
return { data, loading, skeletonLoading, handleGetMoreInfo }
},
}
</script>
<template>
<div class="app-store-container">
<h1>应用商店大全</h1>
<div class="btn">
<a-button type="primary" @click="handleGetMoreInfo">点击获得更多应用信息</a-button>
</div>
<div class="loading" v-if="loading"><a-spin />加载中...</div>
<div v-else class="app-store-list">
<div class="app-store-item" v-for="(item, index) in data" :key="index">
<a-skeleton :loading="skeletonLoading" active :paragraph="{ rows: 2 }">
<div class="app-store-name">{{ item.name }}</div>
<div class="app-store-describe">{{ item.describe }}</div>
</a-skeleton>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.app-store-container {
width: 100%;
min-height: 100vh;
background-color: rgb(244, 250, 194);
h1 {
text-align: center;
padding: 20px 0;
}
.btn {
text-align: end;
margin: 30px 20px;
}
.loading {
height: calc(100vh - 200px);
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
}
.app-store-list {
display: grid;
font-size: 18px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
flex-wrap: wrap;
.app-store-item {
min-width: 180px;
padding: 25px 10px 30px;
margin: 10px;
border: solid 1px #ccc;
background-color: rgb(245, 236, 157);
.app-store-name {
padding-bottom: 10px;
}
.app-store-describe {
line-height: 35px;
}
}
}
@media screen and (max-width: 1000px) and (min-width: 800px) {
.app-store-list {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
@media screen and (max-width: 800px) and (min-width: 600px) {
.app-store-list {
grid-template-columns: 1fr 1fr 1fr;
}
}
@media screen and (max-width: 600px) and (min-width: 400px) {
.app-store-list {
grid-template-columns: 1fr 1fr;
}
}
}
</style>