AdSense

網頁

2026/1/23

Vue Nuxt 3 Skeleton載入中效果

本篇介紹在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-ifv-if-else,當useFetch呼叫[訂單API][GET] /api/orderspending屬性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>
<!--...-->

github



測試

[出口業務]頁面查詢訂單時效果如下。



沒有留言:

AdSense