iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Vue.js

Vue & GraphQL 探險之旅:30天,從新手村到魔王之巔系列 第 15

[Day15] 實戰演練:在 Vue 中,運用 GraphQL 的魔法分頁查詢優化使用者體驗!

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20231015/20141111f8qi7Fo67I.png

在現代的 Web 應用中,使用者體驗是至關重要的。很多時候,網頁載入速度直接影響到使用者的滿意度,特別是當資料量龐大時。GraphQL 是一種允許客戶端明確請求所需資料的查詢語言,透過分頁查詢,我們可以進一步優化使用者體驗,避免一次載入過多不必要的資料。

本次實戰演練中,我們將探討如何在 Vue 框架中運用 GraphQL 的分頁查詢功能,進而優化文章列表頁面的載入速度。而不是一次性讀取全部的一百篇文章,我們會使用分頁技巧,每次只載入部分文章,從而加速頁面的載入並提供更流暢的滾動體驗。


文章範例程式碼 GitHub

範例程式碼 GitHub 連結

Day15 開始前分支:feat/day_14/implement_blog_detail_view_using_variables
Day15 進度完成分支:feat/day_15/enhance_blog_list_view_by_pagination


分頁查詢 Pagination

分頁查詢泛指一種只取出部分資料的技術。當我們面對大量的資料時,一次性地取出所有資料是不實際的,也可能會造成系統的過度負擔。這時,分頁查詢就派上用場,它允許我們基於某些條件(如資料的順序、特定範圍、或用戶的請求)來取出部分資料。

舉一個常見的例子:當使用者在一個電商平台上搜尋商品時,結果可能有上千個商品,但螢幕上只會顯示前 20 筆。當使用者觸發下一個分頁顯示條件時,更多的商品才會被加載顯示。這就是分頁查詢的實際應用。
https://ithelp.ithome.com.tw/upload/images/20231015/20141111Bm2s8E6iGd.png

GraphQL 的分頁查詢

在 GraphQL 的語境中,分頁查詢允許我們以更靈活和高效的方式取得部分資料集。傳統的 RESTful API 中,分頁通常是透過 URL 參數來完成,而在 GraphQL 中,我們可以進一步定制查詢,取得確切所需的資料。

GraphQL 提供了兩種主要的分頁方法:

  1. Offset-based Pagination: 這是最基本的分頁方法,通常使用 limitoffset 參數來確定要取得的資料範圍。

  2. Cursor-based Pagination: 較為先進,且被許多大型應用所採用。它使用特定的 cursor 來標記資料的起始和結束位置,通常結合 firstlast 參數來取得資料。

稍後,本文將會使用基礎的 Offset-based Pagination 作為分頁查詢的示範。

為何分頁查詢對使用者體驗如此重要?

  1. 資料效率: 使用者只需取得他們真正需要的資料。這不僅加速了頁面的載入時間,也減少了不必要的資料傳輸。
  2. 提供更流暢的使用者體驗: 避免因資料過多而造成的頁面卡頓,尤其在移動網絡環境下更為重要。
  3. 前後端解耦: GraphQL 的分頁查詢方法允許前端和後端團隊獨立地進行優化和調整,確保系統的總體效能。

總之,GraphQL 的分頁查詢提供了一種更加高效、靈活和使用者友善的方法來獲取資料,確保應用在各種情境下都能夠提供最佳的使用者體驗。

實戰:運用分頁查詢優化使用者體驗

先前我們選用的 Fake Online GraphQL API — GraphQLZero — 在其文件中明確表示支援分頁功能。
https://ithelp.ithome.com.tw/upload/images/20231015/20141111ywRzB2Cuih.png

因此,我們只需根據該文件指引修改 GraphQL 查詢,即可輕鬆開始實作分頁查詢功能。

撰寫分頁查詢

在 Play Ground 的測試結果中,正如我們所指定的,系統只回傳了前五筆資料。
https://ithelp.ithome.com.tw/upload/images/20231015/20141111LFPyxAuReo.png

Offset-based Pagination 的計算方法:

Offset-based Pagination 主要使用 limitoffset 這兩個參數來定義資料的範圍。

簡單來說,offset 是告訴系統從哪條記錄開始,而 limit 是指定要取得多少筆資料。

假設每頁要顯示 10 筆資料,那麼 limit 就設為 10。而 offset 的值則會根據頁碼而變,計算公式為:(頁碼 - 1) * 每頁資料量

舉例

  1. 如果想要取得第一頁的資料:

    • limit = 10
    • offset = (1 - 1) * 10 = 0
  2. 如果想要取得第三頁的資料:

    • limit = 10
    • offset = (3 - 1) * 10 = 20

通過這種方式,系統知道第三頁的資料是從第 21 筆開始,並取得 10 筆資料。

更新文章列表頁面

完整程式碼範例請參考:feat/day_15/enhance_blog_list_view_by_pagination

in src/views/BlogListView.vue

  1. 引入新的分頁查詢文檔 gqlGetPostsPerPage
  2. 設定分頁查詢所需變數,這裡示範了另一種方式讓 GraphQL Variables 具有響應式
<script setup lang="ts">
// ...

// 設定起始頁面為第一頁面
const defaultPage = 1
// 當前頁碼
const currentPage = ref(defaultPage)
// 一頁幾筆資料
const limit = ref(8)

const { result, loading, error } = useQuery(gqlGetPostsPerPage, () => ({
  options: {
    paginate: {
      page: currentPage.value,
      limit: limit.value,
    },
  },
}))

const posts = computed(() => (result.value?.posts?.data ?? []) as Post[])
const totalCount = computed(() => result.value?.posts?.meta?.totalCount ?? 0)
</script>

<template>
// ...
</template>
  1. 加入 Pagination 元件
<template>
  <!-- ... -->
  <Pagination v-slot="{ page }" :total="totalCount" :items-per-page="limit" :sibling-count="1" show-edges :default-page="defaultPage" class="mt-8">
    <PaginationList v-slot="{ items }" class="flex items-center justify-center gap-1">
      <PaginationFirst />
      <PaginationPrev />

      <template v-for="(item, index) in items">
        <PaginationListItem v-if="item.type === 'page'" :key="index" :value="item.value" as-child>
          <Button class="w-10 h-10 p-0" :variant="item.value === page ? 'default' : 'outline'" @click.prevent="currentPage = item.value">
            {{ item.value }}
          </Button>
        </PaginationListItem>
        <PaginationEllipsis v-else :key="item.type" :index="index" />
      </template>

      <PaginationNext />
      <PaginationLast />
    </PaginationList>
  </Pagination>
</template>

由於之前的重構並採取了模組化的策略,即使我們從撈取大量文章切換到分頁查詢,我們也只需進行如此簡單的修改即可完成分頁功能。

頁面成果

https://ithelp.ithome.com.tw/upload/images/20231015/20141111I7Y2x0z4MA.png

在本次示範中,我們採用了最基礎的分頁實作方式。

這種方法在初級應用上非常方便和直觀,但在資料量龐大的情況下可能會有效能問題。

所以,實務上其實更傾向於使用 Cursor-based Pagination 結合**無限滾動 (infinite scroll) **的方法。這樣不僅可以提供更優質的使用者體驗,也使內容更新更為即時。


效能比較和結果

使用分頁查詢前
https://ithelp.ithome.com.tw/upload/images/20231015/20141111A2yz0tNp6J.png

使用分頁查詢後
https://ithelp.ithome.com.tw/upload/images/20231015/20141111Q30L4LHMzp.png

根據圖片的結果,我們可以觀察到,伺服器的回應時間已經縮短了 1.48254 秒,這意味著我們成功地減少了大約 70% 的等待時間


Recap

透過這次的實戰演練,我們已經學習了如何在 Vue 應用中運用 GraphQL 的分頁查詢技巧,有效地減少不必要的資料載入,提高頁面的載入速度,並且提供更好的使用者體驗。

分頁查詢不僅限於文章列表,同樣的技術也可以應用在其他需要大量資料的場景,如商品列表、用戶列表等。隨著資料量的增加,適時地優化應用將更加重要。

明日預告:探索 GraphQL 條件查詢
準備好深入 GraphQL 的另一項強大功能了嗎?明天,我們將一同探討 GraphQL 的條件查詢,可以更靈活地取得所需要的資料。不只是簡單的查詢,更是按照特定條件來篩選和排序!不要錯過,我們明天見!


上一篇
[Day14] 實戰演練:用 Vue Router & GraphQL Variables 實作文章詳細頁動態查詢
下一篇
[Day16] 實戰演練:在 Vue 中運用 GraphQL 的條件查詢,實現多面貌的搜尋和排序功能
系列文
Vue & GraphQL 探險之旅:30天,從新手村到魔王之巔31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言