news 2026/9/11 15:53:02

Svelte Query 完整 API 参考:@tanstack/svelte-query 类型、函数与上下文体系全解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Svelte Query 完整 API 参考:@tanstack/svelte-query 类型、函数与上下文体系全解

Svelte Query 完整 API 参考:@tanstack/svelte-query 类型、函数与上下文体系全解

【免费下载链接】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/svelte-query的 API 参考指南,以 docs/framework/svelte/reference/index.md 索引为核心骨架,系统梳理其全部类型别名、函数与变量,并结合仓库源码(packages/svelte-query/src)讲解createQuerycreateMutationcreateInfiniteQuerycreateQueries等核心 API 的重载签名、响应式Accessor设计、SSR 水合与上下文机制。读完本文,你将能在 Svelte 5 项目中正确选用并组合这些 API,写出类型安全、支持响应式选项与乐观更新的数据请求代码。

API 全景:索引页揭示的完整公开面

@tanstack/svelte-query的公开 API 被组织为四类:类型别名(Type Aliases)变量(Variables)函数(Functions)引用(References)。索引页完整列出的 26 个类型别名、1 个变量和 17 个函数,正是 packages/svelte-query/src/index.ts 中 re-export 的完整清单。

从索引结构可以清晰看到三条使用主线:

  • 查询与数据获取createQuerycreateInfiniteQuerycreateQueries,配合queryOptionsinfiniteQueryOptions共享选项;
  • 变更与服务端副作用createMutation,配合mutationOptionsuseMutationState跨组件观察状态;
  • 上下文与生命周期QueryClientProviderHydrationBoundaryuseQueryClientuseHydrateuseIsFetchinguseIsMutatinguseIsRestoring

值得注意的细节是,索引页的 References 一节指出QueryClientProvider是对HydrationBoundaryrename + re-export(见 variables/HydrationBoundary.md),这在 packages/svelte-query/src/index.ts#L32-L33 中通过export { default as HydrationBoundary } from './HydrationBoundary.svelte'export { default as QueryClientProvider } from './QueryClientProvider.svelte'得到印证——Svelte Query 使用同一个 Svelte 组件承载「提供客户端」与「水合状态」两项职责。

类型别名体系:从选项到结果的类型契约

索引页列出的 26 个类型别名并非杂乱枚举,它们构成了「选项 → 结果」的完整类型映射。核心定义集中在 packages/svelte-query/src/types.ts:

基础类型Accessor<T>定义为() => T(types.ts#L22),是 Svelte Query 响应式设计的基石——所有create*函数的第一个参数都是Accessor包裹的选项,使得选项可以随 Svelte 响应式状态变化而更新。

查询族

类型别名说明
CreateBaseQueryOptions/CreateBaseQueryResult底层选项与结果,直接透传query-coreQueryObserverOptions/QueryObserverResult
CreateQueryOptions/CreateQueryResultcreateQuery的常规选项与结果
DefinedCreateQueryResult设置了initialData时的结果,data永不为undefined
DefinedInitialDataOptions/UndefinedInitialDataOptions是否携带initialData的选项类型区分
CreateInfiniteQueryOptions/CreateInfiniteQueryResult无限查询的选项与结果
DefinedCreateInfiniteQueryResultinitialData的无限查询结果

变更族CreateMutationOptionsCreateMutationResultCreateMutateFunctionCreateMutateAsyncFunction覆盖mutationFnmutatemutateAsync的类型;MutationTypeFromResult用于从结果反推变更类型,支撑useMutationState的泛型推导。

组合与特殊QueriesOptionsQueriesResults支持createQueries的 tuple/数组推导;HydrationBoundaryQueryClientProviderProps定义水合组件的 props;MutationStateOptions定义useMutationState的过滤器与select参数。

从源码结构看,这些类型绝大多数是对@tanstack/query-coreQueryObserverOptionsMutationObserverOptions等类型的精确定义包装(types.ts#L25-L119),目的是让 Svelte 侧的类型与 core 保持严格一致的同时,裁剪掉_defaulted等内部字段。

createQuery:三种重载对应三种典型场景

createQuery在 packages/svelte-query/src/createQuery.ts 中定义了三个重载(Call Signature),索引页与函数文档分别对应:常规UndefinedInitialDataOptions、带initialDataDefinedInitialDataOptions、以及更宽泛的CreateQueryOptions。三个重载共享四个泛型参数:

  • TQueryFnData = unknown:queryFn 的原始返回类型
  • TError = Error:错误类型,Svelte 侧默认Error(core 中为DefaultError
  • TData = TQueryFnDataselect转换后的数据类型
  • TQueryKey extends readonly unknown[] = readonly unknown[]:查询键类型

两个可选位置参数:optionsAccessor包裹,支持响应式)与queryClient?Accessor<QueryClient>,不传则取最近上下文的客户端)。

基础用法:status 与派生布尔值

最简单形态——用status区分三种状态,或直接用isPending/isError/isSuccess派生布尔值:

<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' const query = createQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts, })) </script> {#if query.status === 'pending'} Loading... {:else if query.status === 'error'} <span>Error: {query.error.message}</span> {:else} <ul> {#each query.data as post (post.id)} <li>{post.title}</li> {/each} </ul> {/if}

status的取值语义在函数文档中明确给出:无缓存数据显示时pending,最近一次抓取失败为error,有数据可展示为successisPending/isSuccess/isError只是方便阅读的派生布尔值。

initialData 重载:data 永不为 undefined

当设置了initialData时,TypeScript 自动选择第二个重载,返回DefinedCreateQueryResult——此时status的类型层面永不解析为pending,即使重新抓取失败,旧数据也会保留:

<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' // `data` 是 `Post[]`,永不 undefined——即便 refetch 失败,列表也保持可见 const query = createQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts, initialData: [], })) </script> {#if query.isError} <span>Error: {query.error.message}</span> {/if} <ul> {#each query.data as post (post.id)} <li>{post.title}</li> {/each} </ul>

高级模式:select、依赖查询与分页

createQuery文档提供了四个实战级示例,覆盖数据获取场景的高频诉求:

1.select派生数据——缓存仍存完整的Post[],但组件拿到的datanumber,且不会污染缓存:

const query = createQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts, select: (posts) => posts.length, }))

2. 依赖查询——postId未就绪时禁用查询。注意文档的提醒:禁用期间要用isLoading而非isPending,否则会误显示 loading:

let { postId }: { postId: number | undefined } = $props() const query = createQuery(() => ({ queryKey: ['post', postId], queryFn: () => fetchPost(postId!), enabled: postId != null, }))

3. 从缓存列表种子化详情查询——用initialData函数形式从已缓存的列表数据中取出详情,跳过加载态:

const queryClient = useQueryClient() const query = createQuery(() => ({ queryKey: ['post', postId], queryFn: () => fetchPost(postId), initialData: () => queryClient .getQueryData<Array<Post>>(['posts']) ?.find((post) => post.id === postId), }))

4. 分页保持旧数据可见——placeholderData: keepPreviousData配合isPlaceholderData禁用下一页按钮:

let page = $state(0) const query = createQuery(() => ({ queryKey: ['posts', page], queryFn: () => fetchPosts(page), placeholderData: keepPreviousData, }))

createInfiniteQuery:无限滚动与分页加载

createInfiniteQuery(packages/svelte-query/src/createInfiniteQuery.ts)同样有三个重载,泛型在查询族基础上增加TPageParam = unknownTData默认值为InfiniteData<TQueryFnData, unknown>。其返回结果在CreateQueryResult基础上增加fetchNextPage/fetchPreviousPage/hasNextPage/hasPreviousPage四个分页能力。

Load More 按钮模式

通过initialPageParam指定起始页码,getNextPageParam从最后一页推导下一页参数:

<script lang="ts"> import { createInfiniteQuery } from '@tanstack/svelte-query' const query = createInfiniteQuery(() => ({ queryKey: ['projects'], queryFn: ({ pageParam }) => fetchProjects(pageParam), initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.nextId, })) </script> {#if query.isPending} Loading... {:else if query.isError} <span>Error: {query.error.message}</span> {:else} <ul> {#each query.data.pages as page} {#each page.projects as project (project.id)} <li>{project.name}</li> {/each} {/each} </ul> <button onclick={() => query.fetchNextPage()} disabled={!query.hasNextPage || query.isFetching} > {query.isFetchingNextPage ? 'Loading more...' : query.hasNextPage ? 'Load More' : 'Nothing more to load'} </button> {/if}

IntersectionObserver 无限滚动模式

用 Svelte 5 的$effect+bind:this挂载哨兵元素,滚动到底部自动加载:

let sentinel: HTMLDivElement | undefined = $state() $effect(() => { if (sentinel == null || !query.hasNextPage || query.isFetching) return const observer = new IntersectionObserver(([entry]) => { if (entry?.isIntersecting) query.fetchNextPage() }) observer.observe(sentinel) return () => observer.disconnect() })

createMutation:服务端副作用与乐观更新

与查询不同,变更通常用于创建/更新/删除数据或执行服务端副作用。createMutation(packages/svelte-query/src/createMutation.svelte.ts)的泛型为TData = unknownTError = ErrorTVariables = voidTContext = unknown,返回CreateMutationResult

基础:mutate 触发 + 成功后失效查询

<script lang="ts"> import { createMutation, useQueryClient } from '@tanstack/svelte-query' const queryClient = useQueryClient() const addMutation = createMutation(() => ({ mutationFn: addTodo, onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), })) </script> <button onclick={() => addMutation.mutate('Item')}>Add</button>

调用点回调与批量提交

mutate/mutateAsync都接受第二个参数传入onSuccess/onError/onSettled回调,适合在调用点做导航等副作用,而不用耦合共享的变更定义。关键语义:若连续多次请求,onSuccess只会在最近一次调用后触发;mutateAsync则每次调用返回独立的 Promise,可逐个等待:

async function handleAddAll(todos: Array<string>) { try { await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo))) } catch (error) { console.error('Failed to add todos:', error) } }

若希望各请求独立失败也能拿到各自结果,文档建议换用Promise.allSettled,避免第一个 reject 就丢失其余结果信息。

乐观更新三件套:onMutate / onError / onSettled

文档给出了完整的乐观更新闭环:onMutate中取消进行中的查询、快照旧数据、写入新数据并返回onMutateResult;失败时onError用快照回滚;最后onSettled统一失效查询:

const addMutation = createMutation(() => ({ mutationFn: addTodo, onMutate: async (newTodo: string) => { await queryClient.cancelQueries({ queryKey: ['todos'] }) const previousTodos = queryClient.getQueryData<Array<string>>(['todos']) queryClient.setQueryData<Array<string>>(['todos'], (old) => [ ...(old ?? []), newTodo, ]) // 失败时传给 onError 作为 onMutateResult return { previousTodos } }, onError: (_err, _newTodo, onMutateResult) => { queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['todos'] }) }, }))

createQueries:并行查询与结果合并

createQueries(packages/svelte-query/src/createQueries.svelte.ts)接收一个对象:queries数组(每个元素是一个查询选项,支持 tuple 类型推导)+ 可选combine函数,整体由Accessor包裹实现响应式。返回按queries顺序排列的结果数组;提供combine时返回combine的产物。

let { ids }: { ids: Array<number> } = $props() const postQueries = createQueries(() => ({ queries: ids.map((id) => ({ queryKey: ['post', id], queryFn: () => fetchPost(id), staleTime: Infinity, })), }))

配合combine把多个查询聚合成单一对象,方便统一渲染:

const combined = createQueries(() => ({ queries: ids.map((id) => ({ queryKey: ['post', id], queryFn: () => fetchPost(id), })), combine: (postQueries) => ({ data: postQueries.map((query) => query.data), isPending: postQueries.some((query) => query.isPending), isError: postQueries.some((query) => query.isError), }), }))

选项构造器:queryOptions / infiniteQueryOptions / mutationOptions

这三者在 index.md 中并列,用于把选项定义与组件解耦,既可在create*中共享,也能被queryClient.queryqueryClient.infiniteQuery等命令式 API 复用。

  • queryOptions(packages/svelte-query/src/queryOptions.ts):queryKey必填,返回值使queryKey携带推断出的数据类型(QueryKeyWithDataTag)。有initialData与无initialData两个重载。典型用法是参数化工厂,按id复用同一套选项:
const postOptions = (id: string) => queryOptions({ queryKey: ['post', id], queryFn: () => fetchPost(id), }) const query = createQuery(() => postOptions(id))
  • infiniteQueryOptions(packages/svelte-query/src/infiniteQueryOptions.ts):同样queryKey必填,TData默认InfiniteData<TQueryFnData, unknown>。可用initialData: { pages: [], pageParams: [] }跳过首屏加载态:
const projectsOptions = infiniteQueryOptions({ queryKey: ['projects'], queryFn: ({ pageParam }) => fetchProjects(pageParam), initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.nextId, initialData: { pages: [], pageParams: [] }, })
  • mutationOptions(packages/svelte-query/src/mutationOptions.ts):两个重载的关键差异在于mutationKey——带mutationKey的重载返回WithRequired<..., "mutationKey">,可用于useMutationState跨组件查询变更状态;不带的重载返回Omit<..., "mutationKey">
const createPostOptions = mutationOptions({ mutationKey: ['posts', 'create'], mutationFn: createPost, }) const pending = useMutationState({ filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' }, })

上下文机制:QueryClient 的存取与恢复状态

Svelte Query 依赖 Svelte 的 context API 传递QueryClient。核心实现在 packages/svelte-query/src/context.ts:

  • setQueryClientContext(client)通过setContext(Symbol('QueryClient'), client)写入;
  • getQueryClientContext()通过getContext读取,找不到时会抛出"No QueryClient was found in Svelte context. Did you forget to wrap your component with QueryClientProvider?"(context.ts#L14-L23),这解释了为什么所有create*函数都必须处于QueryClientProvider之下;
  • setIsRestoringContext/getIsRestoringContextSymbol('isRestoring')为键存取恢复状态布尔值,getIsRestoringContext在取不到时安全回退为{ current: false },不会抛错。

useQueryClient(packages/svelte-query/src/useQueryClient.ts)是对getQueryClientContext的薄封装,可传可选参数指定自定义客户端,否则取最近上下文。

useIsRestoring用于在持久化恢复过程中抑制抓取,配合 packages/svelte-query/src/useIsRestoring.ts 读取 context 中的恢复标记。

全局状态观察:useIsFetching / useIsMutating / useMutationState

这类函数让「不在同一组件内的请求/变更」也能被全局观察到:

  • useIsFetching(filters?, queryClient?)(packages/svelte-query/src/useIsFetching.svelte.ts)返回ReactiveValue<number>——注意返回值是响应式容器,需读.current取当前正在抓取的查询数量。filters可传QueryFilters收窄范围(如{ queryKey: ['posts'] }),省略则统计全部:
const isFetchingPosts = useIsFetching({ queryKey: ['posts'] }) {#if isFetchingPosts.current} <span>Refreshing posts...</span> {/if}
  • useIsMutating与前者对称,统计匹配过滤条件的进行中变更数量,常用于全局「保存中…」指示。

  • useMutationState(options?, queryClient?)(packages/svelte-query/src/useMutationState.svelte.ts)可访问任何匹配filters的变更——包括由其他组件或 hook 创建、甚至已卸载的。optionsMutationStateOptions(默认{}),含filters与可选的select。返回值是对每个匹配变更应用select后的数组:

const pendingVariables = useMutationState({ filters: { status: 'pending' }, select: (mutation) => mutation.state.variables, }) {pendingVariables.length} posts saving...

文档还提示一个重要细节:每次mutate调用都会在变更缓存中保留一个条目直到gcTime过期,因此取useMutationState返回数组的最后一个元素即最近一次成功的变更(配合status: 'success'过滤):

const savedPosts = useMutationState({ filters: { mutationKey: ['posts'], status: 'success' }, select: (mutation) => mutation.state.data, }) const latestSavedPost = $derived(savedPosts[savedPosts.length - 1])

SSR 与状态水合:useHydrate / HydrationBoundary

useHydrate(state?, options?, queryClient?)(packages/svelte-query/src/useHydrate.ts)把之前dehydrate出的状态并入queryClient;若客户端已有数据,会基于更新时间戳智能合并。HydrationBoundary是对它的封装,日常 SSR 场景直接使用组件形式即可——除非需要在自定义组件中手动触发水合,才直接用useHydrate

典型的 SSR 流程:服务端 load 函数用queryClient.query预取并dehydrate(queryClient),客户端通过 props 接收dehydratedState交给HydrationBoundary

<script lang="ts"> import { HydrationBoundary } from '@tanstack/svelte-query' import type { DehydratedState } from '@tanstack/svelte-query' import Posts from './Posts.svelte' let { dehydratedState }: { dehydratedState: DehydratedState } = $props() </script> <HydrationBoundary state={dehydratedState}> <Posts /> </HydrationBoundary>

扩展阅读与源码索引

围绕本文涉及的 API,可在仓库中继续深入:

  • 全部类型别名与函数的逐条签名:docs/framework/svelte/reference/type-aliases 与 docs/framework/svelte/reference/functions
  • Svelte Query 实现源码:packages/svelte-query/src/index.ts、createQuery.ts、createMutation.svelte.ts、context.ts、types.ts
  • 框架总览与安装方式:docs/framework/svelte/overview.md、docs/framework/svelte/installation.md
  • Svelte Query 官方示例(basic、load-more-infinite-scroll、optimistic-updates、ssr 等):examples/svelte
  • Svelte 5 迁移说明:docs/framework/svelte/migrate-from-v5-to-v6.md

理解这些 API 时把握三条主线即可:查询createQuery/createInfiniteQuery/createQueries加选项构造器共享定义;变更createMutation配合useMutationState实现跨组件观察与乐观更新;上下文QueryClientProvider提供、useQueryClient消费,SSR 场景经dehydrate/HydrationBoundary完成状态交接。

【免费下载链接】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

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 15:51:29

AI产品开发:从场景挖掘到可行性验证的实战指南

1. 项目概述&#xff1a;AI产品从零开始的必经之路 在AI技术快速发展的今天&#xff0c;如何将一个模糊的想法转化为真正落地的AI产品&#xff0c;是许多创业者和产品经理面临的共同挑战。我最近完成了一个从零开始的AI产品设计项目&#xff0c;深刻体会到场景挖掘与可行性验证…

作者头像 李华
网站建设 2026/9/11 15:51:12

华为硬件校招机试备考指南:从电路基础到单板开发全覆盖

这套“华为2026届校招实习硬件技术工程师&#xff08;硬件通用/单板开发&#xff09;机试”的资料&#xff0c;14套题、每套40题&#xff0c;我第一次拿到时第一反应是&#xff1a;这哪是刷题&#xff0c;这是在用考题帮你把大学四年硬件课重新捋一遍。身边好几个准备投华为硬件…

作者头像 李华
网站建设 2026/9/11 15:50:19

垃圾短信识别全流程:从文本分类到阈值调优的数据挖掘闭环

简介&#xff1a;面向网络数据挖掘课程设计/实训场景的垃圾短信识别系统完整工程&#xff0c;涵盖数据预处理、特征构建、模型训练与分类等环节&#xff0c;配有实验报告、操作说明及可运行的Python和MATLAB代码&#xff0c;适合高校学生用于课设、大作业或毕业设计参考复现。压…

作者头像 李华
网站建设 2026/9/11 15:49:41

CBox央视影音客户端下载安装教程

概述 CBox 央视影音是央视网&#xff08;中国网络电视台 CNTV&#xff09;出品的官方视频客户端&#xff0c;提供央视及百余路卫视、地方频道的电视直播、时移回看、节目点播等功能&#xff0c;全部免费。本文讲清安装与核心功能使用。 一、下载与安装 从 CBox央视影音下载中…

作者头像 李华
网站建设 2026/9/11 15:49:00

金融与运营商实时计算平台ZCBUS架构解析与实践

1. 项目背景与行业痛点ZCBUS实时计算平台在金融与运营商行业的落地&#xff0c;本质上是对传统批处理模式的一次革命性突破。这两个行业长期面临着数据时效性与处理能力的双重挑战&#xff1a;金融行业每天需要处理数以亿计的交易流水&#xff0c;风控系统对实时性的要求精确到…

作者头像 李华