:用 defaultOptions 為 injectQuery 省去逐條聲明)
TanStack Query Angular 默認 queryFn 實戰(zhàn)用 defaultOptions 為 injectQuery 省去逐條聲明【免費下載鏈接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.項目地址: https://gitcode.com/GitHub_Trending/qu/query本篇技術指南基于 TanStack QueryAngular 適配器 tanstack/angular-query-experimental的 default-query-function 指南講解如何通過QueryClient的defaultOptions.queries.queryFn注冊一個全局默認查詢函數(shù)從而讓injectQuery只需傳入queryKey即可完成數(shù)據(jù)獲取。讀完本文你將掌握完整可運行的示例寫法并能在源碼層面理解默認值是如何與每次調用的 options 合并、覆蓋的。核心思路把「怎么取數(shù)據(jù)」聲明一次把「取什么」留給組件在典型的 REST 應用里絕大多數(shù)查詢的差異只在于 URL 路徑即queryKey而請求方式axios/fetch 實例、認證頭、錯誤歸一化、數(shù)據(jù)解包是高度一致的。如果每個組件都寫一遍queryFn: () axios.get(...).then(r r.data)會產(chǎn)生大量重復代碼且請求層難以統(tǒng)一替換比如全局換 baseURL、統(tǒng)一注入 token。TanStack Query 的解法就是「默認查詢函數(shù)」Default Query Function在創(chuàng)建QueryClient時通過defaultOptions.queries.queryFn提供一個QueryFunction之后所有查詢在自身未顯式聲明queryFn時都會回落到這個默認實現(xiàn)并且queryFn能收到完整的QueryFunctionContext含queryKey因此可以根據(jù) key 動態(tài)拼接請求路徑。完整示例從定義到組件使用下面完整繼承官方指南中的示例代碼覆蓋「定義默認函數(shù) → 注冊到客戶端 → 接入 Angular 應用 → 組件中只傳 key」四個環(huán)節(jié)。定義并注冊 defaultQueryFn// Define a default query function that will receive the query key const defaultQueryFn: QueryFunction async ({ queryKey }) { const { data } await axios.get( https://jsonplaceholder.typicode.com${queryKey[0]}, ) return data } // provide the default query function to your app with defaultOptions const queryClient new QueryClient({ defaultOptions: { queries: { queryFn: defaultQueryFn, }, }, })要點說明默認函數(shù)簽名是QueryFunction接收一個上下文對象其中最常用的是queryKey。示例中把queryKey[0]直接當作 API 路徑如/posts、/posts/1拼接到 jsonplaceholder 的 baseURL 上這是一種「key 即路由」的約定defaultOptions.queries是全局查詢默認值的掛載點除了queryFn還可以放staleTime、retry等本文聚焦queryFnQueryClient構造器會把傳入的defaultOptions保存下來config.defaultOptions || {}后續(xù)所有defaultQueryOptions(...)調用都從這里讀取見 QueryClient 構造函數(shù)。把客戶端接入 Angular 應用bootstrapApplication(MyAppComponent, { providers: [provideTanStackQuery(queryClient)], })provideTanStackQuery內部通過provideQueryClient把QueryClient注冊為可注入的單例并在 injector 銷毀時調用client.unmount()、創(chuàng)建時調用client.mount()源碼見 providers.ts。它也支持傳入InjectionToken以支持懶加載路由單獨掛載 Query并可通過withDevtools()啟用開發(fā)者工具文檔見 providers.ts 的 JSDoc。組件中只傳 queryKeyexport class PostsComponent { // All you have to do now is pass a key! postsQuery injectQueryArrayPost(() ({ queryKey: [/posts], })) // ... } export class PostComponent { // You can even leave out the queryFn and just go straight into options postQuery injectQueryPost(() ({ enabled: this.postIdSignal() 0, queryKey: [/posts/${this.postIdSignal()}], })) // ... }兩個細節(jié)值得注意injectQuery接收一個 options 函數(shù)() options而非字面量對象。從 createBaseQuery.ts 的注釋可以確認這是刻意設計options 被包在函數(shù)里后內部嵌入的 signal 表達式如this.postIdSignal()才能被 Angular 的響應式系統(tǒng)追蹤signal 變化時默認選項和 observer 才會自動重算。queryFn被整體省略后類型系統(tǒng)依然完整。injectQuery的泛型參數(shù)ArrayPost/Post直接決定了返回值信號的類型無需本地聲明返回Promise的函數(shù)query-options.ts中的UnusedSkipTokenOptions與DefinedInitialDataOptions等類型正是把queryFn聲明為可選字段的依據(jù)見 query-options.ts。源碼層面默認 queryFn 是如何生效的第一步createBaseQuery 用 computed 應用全局默認值injectQuery與injectInfiniteQuery共享同一個底層工廠createBaseQuery。其中defaultedOptionsSignal是一個computed每次求值都會調用queryClient.defaultQueryOptions(optionsFn())把組件傳入的 options 與全局默認值合并const defaultedOptionsSignal computed(() { const defaultedOptions queryClient.defaultQueryOptions(optionsFn()) defaultedOptions._optimisticResults isRestoring() ? isRestoring : optimistic return defaultedOptions })見 create-base-query.ts。由于它是computed當optionsFn()內引用的 signal例如postIdSignal變化時合并結果會重新計算enabled、queryKey等也隨之更新。第二步QueryClient.defaultQueryOptions 的合并順序合并邏輯在 QueryClient.defaultQueryOptions 中核心是三段展開const defaultedOptions { ...this.#defaultOptions.queries, // ① 全局默認值含我們的 defaultQueryFn ...this.getQueryDefaults(options.queryKey), // ② 按 key 前綴匹配的 setQueryDefaults ...options, // ③ 本次調用顯式傳入的 options _defaulted: true, }從源碼結構看優(yōu)先級由低到高是defaultOptions.queries構造QueryClient時傳入全局生效setQueryDefaults(queryKey, options)注冊的按 key 前綴匹配的默認值getQueryDefaults通過partialMatchKey做前綴匹配見 queryClient.ts每次injectQuery傳入的 options可以覆蓋默認queryFn或任何其它字段。這意味著全局注冊defaultQueryFn之后某個特殊查詢仍可在 options 里寫自己的queryFn覆蓋它也可以只對/posts/*這一族 key 用setQueryDefaults提供局部默認值而不影響其它 key。方法還會補全若干派生默認值如refetchOnReconnect、throwOnError、networkMode并對skipToken做enabled false的轉換見 queryClient.ts。帶_defaulted標記的對象會被直接短路返回避免重復合并。第三步Query 執(zhí)行時如何找到 queryFn真正發(fā)起請求前Query會在this.options.queryFn缺失時從已訂閱的 observer 中找出攜帶queryFn的那個作為兜底defaultOptions.queries.queryFn正是在合并階段被放進了 observer optionsif (!this.options.queryFn) { const observer this.observers.find((x) x.options.queryFn)見 query.ts。隨后通過ensureQueryFn(this.options, fetchOptions)解析出最終函數(shù)并以其構造QueryFunctionContext執(zhí)行query.ts。這條鏈路解釋了為什么「組件里不寫 queryFn」仍然能發(fā)起請求默認值在 observer 合并期就已經(jīng)掛到 options 上執(zhí)行期只是讀取。默認值、queryOptions 與類型安全如果你偏好把查詢配置抽到組件外部復用可以用同包的queryOptions幫助函數(shù)query-options.ts。它本身只是恒等函數(shù)價值在于三個重載為queryKey打上queryFn的數(shù)據(jù)類型標簽const { queryKey } queryOptions({ queryKey: [key], queryFn: () Promise.resolve(5), // ^? Promisenumber })打上標簽后queryClient.getQueryData(queryKey)的返回值類型就是number | undefined而不是unknown。把queryOptions與全局defaultQueryFn結合時抽出的配置可以只含queryKey數(shù)據(jù)獲取細節(jié)全部交給默認函數(shù)同時保持端到端的類型推斷。實踐建議與邊界結合倉庫實現(xiàn)給出幾條落地時的注意點讓 key 成為「請求路徑」的前提是請求層可控。示例中queryKey[0]直接拼 URL適合 REST 且路徑結構穩(wěn)定的 API對 GraphQL 或非路徑型 key默認函數(shù)應按 key 結構分派從queryKey首元素判斷資源類型再選擇對應請求邏輯。默認函數(shù)里做集中式錯誤/響應歸一化。既然queryFn是全局單點axios 攔截器式的解包return data、錯誤映射都適合放在這里各組件無需感知。局部覆蓋優(yōu)于復制粘貼個別查詢的取數(shù)邏輯確實不同時在該次injectQuery的 options 中顯式寫queryFn即可合并順序的第 ③ 層不要為此拆出第二個QueryClientprovideQueryClient的文檔注釋也說明它更適用于應用局部或單元測試場景見 providers.ts。響應式依賴依賴 options 函數(shù)。默認queryFn的注冊是「應用級靜態(tài)配置」而enabled、queryKey這類與 signal 相關的字段必須在 options 函數(shù)內引用 signal如示例的this.postIdSignal() 0才會隨信號更新——這是 createBaseQuery.ts 注釋中強調的行為。適用前提defaultOptions.queries.queryFn由 query-core 提供Angular 側經(jīng)由tanstack/angular-query-experimental的provideTanStackQuery注入客戶端后自動生效版本行為以本倉庫當前 query-core 源碼 與 Angular 適配器源碼 為準。小結默認 queryFn 模式把「如何請求」從 N 個組件收斂到 1 處QueryClient配置defaultQueryFn接收queryKey動態(tài)構造請求provideTanStackQuery(queryClient)完成應用級注入injectQuery(() ({ queryKey: [...] }))則讓組件代碼退化為「聲明 key 泛型類型」。源碼鏈路上computed包裹的defaultQueryOptions合并全局默認 → 按 key 前綴默認 → 調用方 options與Query執(zhí)行期的queryFn兜底查找共同保證了這套省略寫法在響應式更新下的正確性。倉庫中的 Angular 示例應用bootstrapApplicationappConfig提供provideTanStackQuery可直接作為搭建起點?!久赓M下載鏈接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.項目地址: https://gitcode.com/GitHub_Trending/qu/query創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考