本篇介紹在Vue Nuxt 3專案使用Skeleton來呈現載入中的效果。
Skeleton又叫Skeleton Screen,中文稱為「骨架屏」,用於在網頁中顯示載入中的區塊,讓使用者可以知道載入後的資料的範圍和位置,是種提升使用者體驗的技巧。
目前專案在[出口業務]頁面查詢[訂單]列表時,API回應資料之前畫面是顯示"資料載入中...",接下來會改用Skelelon元件來顯示載入中的效果。
事前要求
參考「Vue Nuxt 3 抽取下拉選單為元件(Components) 」。
參考「Vue Nuxt 3 分頁」。
新增Skelton元件
在專案根目錄下的components目錄中新增SkeletonList.vue元件。
components/SkeletonList.vue
<template>
<div class="skeleton">
<div v-for="n in count" :key="n" class="skeleton-item"></div>
</div>
</template>
<script setup lang="ts">
defineProps({
count: { type: Number, default: 5 }
})
</script>
<style scoped>
.skeleton {
margin: 12px;
width: 400px;
}
.skeleton-item {
height: 18px;
margin: 8px 0px;
background: #ddd;
border-radius: 4px;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.4; }
100% { opacity: 1; }
}
</style>
使用Skeleton元件
在[出口業務]頁面pages/home/export/index.vue中,把原本的"資料載入中..."區塊替換成<SkeletonList>元件即可。搭配Vue條件渲染指令v-if、v-if-else,當useFetch呼叫[訂單API][GET] /api/orders的pending屬性orderPending為true,也就是資料仍在載入時,顯示Skeleton元件;當資料回傳後orderPending為false,則顯示訂單資料。
pages/home/export/index.vue
<template>
<div>
<h1>出口業務</h1>
<label>
訂單狀態:
<input v-model="status" placeholder="pending/done">
</label>
<br>
<label>
出口國家:
<CountrySelect v-model="country" />
</label>
<br>
<button @click="search">查詢</button>
<SkeletonList v-if="orderPending" :count="pageSize" />
<p v-else-if="error" class="error">資料載入失敗</p>
<p v-else-if="result.data.length === 0">沒有訂單資料</p>
<ul v-else>
<li v-for="order in result?.data" :key="order.id">
<NuxtLink :to="`/home/export/${order.id}`">
訂單 #{{ order.id }},
狀態: {{ order.status }},
出口國家:{{ countryMap?.[order.country] ?? order.country }}
</NuxtLink>
</li>
</ul>
<!-- 分頁按鈕 -->
<button @click="prevPage" :disabled="orderPending || currentPage <= 1">上一頁</button>
<span>第 {{ currentPage }} 頁 / 共 {{ totalPages }} 頁</span>
<button @click="nextPage" :disabled="orderPending || currentPage >= totalPages">下一頁</button>
</div>
</template>
<script setup lang="ts">
// ...
const { data: result, pending: orderPending, error, refresh } = useFetch<OrdersResponse>('/api/orders', {
query: {
status: queryStatus,
country: queryCountry,
page: queryPage,
pageSize: queryPageSize
},
default: () => ({ data: [], total: 0, totalPages: 0, page: 1, pageSize }),
})
// ...
</script>
<!--...-->
測試
[出口業務]頁面查詢訂單時效果如下。
沒有留言:
張貼留言