使用 Dependent Queries
與 Disabling Queries
來優化 API 查詢
不喜歡看字的可以看影片:
- Vue3 教學 - Vue Query Part.1 使用 useQuery 與 useMutation
- Vue3 教學 - Vue Query Part.2 資料生命週期與重新獲取機制 (stale,fresh,paused,inActive)
- Vue3 教學 - Vue Query Part.3 使用 placeholderData 與 keepPreviousData 提升分頁體驗
- Vue3 教學 - Vue Query Part.4 使用 useMutation 進行樂觀更新
- Vue3 教學 - Vue Query Part.5 如何使用 enabled 控制查詢與 prefetch 提升使用者體驗
簡介
在 Vue 應用開發中,可能會遇到以下需求:
- 先獲取使用者資訊,再查詢對應的專案資料
- 根據
userIds
批量查詢多個使用者的訊息 - 避免 API 競爭問題,確保查詢順序正確
- 僅在特定條件滿足時才發送查詢請求
Vue Query 提供 Dependent Queries
和 Disabling Queries
,讓我們能夠靈活地控制查詢的觸發條件,提升效能並減少不必要的 API 請求。
依賴查詢 (Dependent Queries)
當查詢 依賴於前一個查詢的結果 時,可以使用 enabled
來控制是否執行。
以下程式碼為:
- 先查詢
user
,再查詢projects
- 避免
projects
查詢在userId
尚未獲取時執行 - 減少不必要的 API 呼叫,提高效能
App.vue
<script setup>
import { useQuery } from "@tanstack/vue-query";
import { computed } from "vue";
import axios from "axios";
const getUserByEmail = async (email) => (await axios.get(`/api/user/${email}`)).data;
const getProjectsByUser = async (userId) => (await axios.get(`/api/projects/${userId}`)).data;
// 取得使用者資訊
const { data: user } = useQuery({
queryKey: ["user", "test@example.com"],
queryFn: () => getUserByEmail("test@example.com"),
});
const userId = computed(() => user.value?.id);
const enabled = computed(() => !!userId.value); // 只有當 userId 存在時才啟用
// 取得該使用者的專案 (依賴 `userId`)
const { data: projects } = useQuery({
queryKey: ["projects", userId],
queryFn: () => getProjectsByUser(userId.value),
enabled, // 依賴 userId,只有 userId 存在時才會執行
});
</script>
停用查詢 (Disabling Queries)
如果我們不希望查詢在元件掛載時自動執行,例如:
- 按鈕觸發查詢
- 表單輸入後才查詢
- 某些條件未滿足時不查詢
這時可以使用 enabled: false
來 停用查詢,僅在 refetch()
才會發送查詢請求。
App.vue
<script setup>
import { useQuery } from "@tanstack/vue-query";
import axios from "axios";
const fetchTodoList = async () => (await axios.get("/api/todos")).data;
// 預設停用查詢,點擊按鈕後手動執行
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ["todos"],
queryFn: fetchTodoList,
enabled: false, // 停用查詢
});
</script>
<template>
<div>
<button @click="refetch">查詢 Todos</button>
<p v-if="isLoading">載入中...</p>
<p v-else-if="isError">查詢失敗</p>
<ul v-else>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
</div>
</template>
延遲查詢 (Lazy Queries)
enabled
也可以用來動態控制查詢何時執行,例如:
- 當使用者輸入關鍵字後才執行查詢
- 只有當某個變數有值時才執行查詢
App.vue
<script setup>
import { useQuery } from "@tanstack/vue-query";
import { ref, computed } from "vue";
import axios from "axios";
const filter = ref(""); // 使用者輸入的篩選條件
const isEnabled = computed(() => !!filter.value); // 只有 filter 有值時才啟用
const fetchTodos = async (filter) => (await axios.get(`/api/todos?filter=${filter}`)).data;
// 只有當 filter 有值時才查詢
const { data } = useQuery({
queryKey: ["todos", filter],
queryFn: () => fetchTodos(filter.value),
enabled: isEnabled,
});
</script>
總結
Dependent Queries
適用於查詢之間有依賴的場景enabled
讓我們可以靈活控制查詢執行時機Disabling Queries
適用於按鈕觸發或使用者輸入條件後的查詢- 透過
Lazy Queries
提升應用效能,減少不必要的請求