资讯详情

Apollo 2 系列:Vue 中 useLazyQuery 按需查询组合式函数完全指南

📅 2026/10/10 2:12:21 | 华诺云谱 👁 阅读
Apollo 2 系列:Vue 中 useLazyQuery 按需查询组合式函数完全指南
前端GraphQL【免费下载链接】apollo Apollo/GraphQL integration for VueJS项目地址https://gitcode.com/gh_mirrors/apollo2/apollo点击查看免费下载useLazyQuery是vue/apollo-composable本项目 Apollo/GraphQL 与 Vue 的集成层中用于按需执行 GraphQL 查询的组合式函数。它适用于变量在组件挂载时未知、必须等用户操作搜索提交、按钮点击、弹窗打开后才发起请求的场景。读完本文你将掌握load()触发机制、完整 Options/Result 契约、错误处理与 SSR 行为并能基于源码理解其底层实现原理。为什么需要 useLazyQuery与 useQuery 的分工在 packages/docs/advanced/lazy-queries.md 中官方给出了三者的选择矩阵场景工具变量来自用户动作搜索框提交、按钮点击useLazyQuery变量已知但希望按条件控制是否执行useQuery({ enabled })变量已知且挂载后立即执行useQuery其核心区别在于useQuery一旦调用就会立即发起请求而useLazyQuery初始处于禁用状态必须显式调用它暴露的load(variables?)函数才会启动。一旦第一次load完成查询便退化为普通的useQuery行为——变量变为响应式、结果自动更新、作用域销毁时自动停止。从源码看这一“先禁用后激活”的实现位于 packages/vue-apollo-composable/src/useLazyQuery.tsuseLazyQuery本身只是对内部实现useQueryImpl(query, options, true)的薄封装其中第三个参数lazy true。在 packages/vue-apollo-composable/src/useQuery.ts 中lazy标志被转换为内部 refforceDisabledconst forceDisabled ref(lazy)并参与最终启用态的计算const isEnabled computed(() enabledOption.value !forceDisabled.value !!document.value)也就是说只要forceDisabled为truewatch(isEnabled)就不会创建ObservableQueryobservableQuery.value client.watchQuery(...)不会执行请求自然不会被发出直到load()调用start()forceDisabled.value false后查询才真正激活。基本用法从文档示例到可运行代码官方函数文档packages/docs/api/composable/functions/useLazyQuery.md给出了最简示例。下面是一个结合响应式模板的完整形态script setup langts import { TypedDocumentNode } from apollo/client import { useLazyQuery } from vue/apollo-composable import { ref } from vue const SearchUsers: TypedDocumentNode{ users: { id: string, name: string }[] }, { term: string } gql query SearchUsers($term: String!) { users(search: $term) { id name } } const term ref() const { load, current } useLazyQuery(SearchUsers) async function search() { const result await load({ term: term.value }) console.log(Found users:, result?.users) } /script template form submit.preventsearch input v-modelterm buttonSearch/button /form div v-ifcurrent.loading Searching... /div ul v-else-ifcurrent.resultState complete li v-foruser in current.result.users :keyuser.id {{ user.name }} /li /ul /template要点query参数类型为MaybeRefOrGetterDocumentNode | TypedDocumentNodeTData, TVariables即可以传文档本身也可以传一个返回文档的 ref 或 getteroptions?参数类型同样为MaybeRefOrGetterOptions支持响应式配置返回值Result提供响应式 refs 与load函数详见下文 Result 章节load(variables?)的行为是把传入变量合并进已有变量源码中为variablesRef.value { ...variablesRef.value, ...variables }然后调用start()启动查询返回一个 Promise——查询完成时以结果数据 resolve出错时以错误 reject。结果除了出现在load的返回值里也会同时落入current.result以及result、loading、error等独立的响应式 refs 中与useQuery的用法完全一致。多次加载变量合并语义load可以被重复调用每次调用都会用新变量重新执行查询const { load } useLazyQuery(SEARCH_USERS) await load({ term: alice }) // 第一次搜索 await load({ term: bob }) // 新搜索每次调用都会把新变量“叠加”在已加载的变量之上merge 而非 replace。因此如果第一次传了{ term: alice }第二次传{ limit: 10 }最终发送的变量会是{ term: alice, limit: 10 }。需要留意的是源码中的超时与等待逻辑load内部使用vueuse/core的until(...).toBe(true, { timeout: 30000 })等待当前状态变为resultState complete且非isPreviousResult或出现error超时上限 30 秒随后若存在错误则直接 throw否则返回queryResult.result.value。这解释了为什么load的 Promise 既可能 resolve 数据也可能 reject 错误。Options完整的配置契约useLazyQuery的选项与useQuery完全一致唯一例外是enabled不可用——因为查询在load()调用之前永远是懒的。从源码类型定义看packages/vue-apollo-composable/src/useLazyQuery.tsexport type OptionsTData, TVariables OmituseQuery.OptionsTData, TVariables, enabled选项按用途分为四组完整参考Options.md。1. 操作选项Operation options选项类型默认值说明errorPolicyErrorPolicynone决定查询在同时返回 GraphQL 错误与部分结果时如何处理none表示结果包含错误详情但不含部分数据variablesReactiveVariablesParameter—查询所需的全部 GraphQL 变量对象每个 key 对应变量名值对应变量值其中variables支持多种响应式形态见 useQuery.ts 中ReactiveVariablesParameter的定义可以传整个变量的 ref/getter也可以传一个“逐个变量映射到 ref/getter”的对象例如const id ref(1) useQuery(query, { variables: { id } })useLazyQuery场景下options.variables充当load()的默认变量先调用load()不传参时使用选项中的响应式变量调用load({...})传参时则将其合并覆盖。2. 网络选项Networking options选项类型默认值说明contextDefaultContext—若使用 Apollo Link作为沿 link 链传递的context对象的初始值notifyOnNetworkStatusChangebooleanfalse为true时每当网络状态变化或发生网络错误就触发下一次状态事件pollIntervalnumber0不轮询查询轮询更新结果的间隔毫秒skipPollAttempt()() boolean—轮询期间每次尝试 refetch 前调用返回true则跳过本次 refetch直到下一个轮询周期再试3. 缓存选项Caching options选项类型默认值说明fetchPolicyWatchQueryFetchPolicycache-first查询与 Apollo Client 缓存的交互方式是否先查缓存再发请求initialFetchPolicyWatchQueryFetchPolicy跟随fetchPolicy指定变量变化时应回退到的策略除非nextFetchPolicy介入nextFetchPolicy策略或回调—本次查询完成之后使用的FetchPolicyrefetchWritePolicyRefetchWritePolicymerge兼容 Apollo Client 3.xNetworkStatus.refetch操作写入缓存时是合并现有字段数据还是整体覆盖覆盖通常更合适returnPartialDatabooleanfalse为true时若缓存未包含全部查询字段允许返回部分结果4. Vue-Apollo 专属选项Vue-Apollo options选项类型默认值说明awaitCompletebooleanfalse是否等待数据完整后再 resolve配合stream/defer指令使用仅影响 SSR 预取与await useQuery()clientIdstring—指定要使用的具名 Apollo Client 的 ID替代默认 clientdebouncenumber—变量更新的防抖毫秒数keepPreviousResultbooleanfalse加载新数据时保留上一份结果保留结果仍以正常结果上报resultState、result、partial描述它并带isPreviousResult: true标记以便区分prefetchbooleantrue是否在服务端预取throttlenumber—变量更新的节流毫秒数从 useQuery.ts 的实现可以看到这些选项如何生效Apollo 相关选项fetchPolicy、context、pollInterval等被提取为watchQueryOptionscomputed最终与query、variables合并成传给client.watchQuery()的完整选项Vue-Apollo 专属选项则被提取为vueApolloQueryOptions其中debounce/throttle通过useDebounceFn/useThrottleFnflush: sync的 watcher延迟currentVariables的提交pending标志会在这段窗口期内保持为true。Result完整的返回值契约useLazyQuery的返回值Result继承自useQuery.Result并额外扩展了load函数完整参考Result.md。按用途可分为六组。1. 操作数据Operation data字段类型说明currentRefCurrent当前状态的判别联合类型discriminated unionerrorRefErrorLike \| undefined最近一次查询执行中发生的错误isPreviousResultRefboolean为true时result是keepPreviousResult保留的旧变量结果不对应当前variables此时resultState/result/partial描述保留结果loading/networkStatus/error描述正在替换它的请求resultRefobject \| null查询完成后的结果对象若查询产生一个或多个错误可能为undefined取决于errorPolicycurrent中的resultState取值为empty | complete | streaming | partialempty表示缓存或网络都无法提供数据partial仅在returnPartialData: true时出现streaming表示延迟查询defer仍在流式返回中complete表示结果是完整满足的。2. 网络信息Network info字段类型说明loadingRefboolean查询忙碌中覆盖请求在途、变量等待debounce/throttle计时器以及变量已接受但请求尚未发出的交接期。比networkStatus 7的范围更广networkStatusRefNetworkStatus查询请求的网络状态编号只描述网络本身——pending为true时它仍保持ready。与notifyOnNetworkStatusChange配合使用pendingRefboolean为true时variables已变化且请求已提交但因debounce/throttle尚未发出loading同样覆盖这段窗口用pending可区分“计时器未到”与“请求真的在网络上”3. Refs引用字段类型说明documentRefDocumentNode正在查询的 GraphQL 文档optionsRefOptions当前选项queryRefObservableQuery \| undefined底层 Apollo ObservableQuery 实例查询停止时为undefinedvariablesRefOperationVariables正在发送给查询的变量经过 debounce/throttle 之后4. 生命周期Lifecycleload(variables?)加载查询。若未启动则启动之传入的变量会与选项中的变量合并。返回Promiseobject | undefined查询完成时 resolve 数据出错时 reject。useLazyQuery的独有方法也是它区别于useQuery的关键start()启动查询若查询已激活或enabled为false则无效果stop()停止查询可随时通过start()重新启动restart()停止并重启查询返回Promisevoid。5. 查询方法Query methodsfetchMore(options)为分页/无限滚动加载更多数据完成后响应式 refs 自动更新。数据合并有两种方式一是updateQuery回调手动合并fetchMoreResult与previousQueryResult二是在 Apollo 缓存配置中定义字段级merge函数。注意若使用fetchPolicy: no-cache必须提供updateQuery。const { result, fetchMore } useQuery(GetPosts, { variables: { offset: 0, limit: 10 } }) async function loadMore() { await fetchMore({ variables: { offset: result.value.posts.length }, updateQuery: (previousQueryResult, { fetchMoreResult }) ({ ...previousQueryResult, posts: [...previousQueryResult.posts, ...fetchMoreResult.posts] }) }) }refetch(variables?)可选携带新变量重新执行查询适合“刷新”按钮、下拉刷新等命令式场景。注意两点需要与响应式变量保持同步的变量应放在options.variables中如路由参数、表单输入一次性命令式获取才用refetch()传入refetch的变量是临时的仅用于这一次请求暴露的variablesref 不会更新之后响应式options.variables变化时查询会使用选项中的值而非 refetch 传入的值。await refetch() // 用当前变量重新执行 await refetch({ id: other-user }) // 仅本次使用的新变量subscribeToMore(options)通过 GraphQL subscription 为查询增加实时数据订阅数据到达时由updateQuery合并进现有结果。订阅在查询停止或组件卸载时自动清理也可调用返回的函数手动取消const unsubscribe subscribeToMore({ document: OnMessageAdded, variables: { channelId }, updateQuery: (_, { previousData, subscriptionData }) { if (!subscriptionData.data) return previousData return { ...previousData, messages: [...previousData.messages, subscriptionData.data.messageAdded] } } })updateQuery(mapFn)直接更新缓存的查询结果适用于乐观更新或免网络请求的数据修改写入缓存后响应式 refs 自动更新。文档建议谨慎使用多数缓存更新应优先考虑缓存字段策略或client.writeQueryupdateQuery绕过了 Apollo 常规缓存更新机制适合快速本地修改function addOptimisticTodo(todo: Todo) { updateQuery((_, { previousData }) ({ ...previousData, todos: [...previousData.todos, todo] })) }6. 事件Events事件触发时机onNextState最细粒度事件每次状态更新都会触发含 loading 状态、网络状态变化、结果更新onResult收到查询结果数据时resultState为complete、partial、streaming时触发empty状态与错误不触发onCompleteResult仅当resultState为complete时触发onPartialResult仅当resultState为partial时触发需要returnPartialData: trueonStreamingResult仅当resultState为streaming时触发配合defer/stream指令onError查询发生错误时触发事件底层由vueuse/core的createEventHook实现见 useQuery.ts 的 Events 区域事件分发通过triggerResultEvents依据resultState路由到对应 hook。等待结果与错误处理load返回 Promise因此可以内联使用结果async function fetchUser(id: string) { try { const data await load({ id }) if (data) { console.log(Loaded:, data.user) } } catch (e) { console.error(Failed to load:, e) } }Promise 在结果完整时以查询数据 resolve查询出错时以错误 reject。无论成败响应式 refscurrent、result、error都会同步更新。这一行为由源码中的等待循环保证load等待resultState complete且非保留结果或error ! null二者之一超时 30 秒一旦queryResult.error.value存在即 throw。SSR 场景下的行为useLazyQuery不会在服务端运行——因为服务端不存在触发它的用户动作。如果某个值需要在 SSR 阶段就可用请改用useQuery参见 packages/docs/ssr/overview.md。从源码也可印证useQueryImpl中注册onServerPrefetch时要求isEnabled.value为真才会预取而懒查询在服务端渲染阶段forceDisabled仍为true故不会触发预取。兼容层与 v4 行为的映射仓库中还有一套兼容实现 packages/vue-apollo-composable/src/compat/useLazyQuery.ts用于对齐 v4 的useLazyQuery语义差异值得了解load 签名load(document?, variables?)可携带文档覆盖与变量覆盖v4 语义下变量是替换replace而非 v5 的合并merge重复调用首次调用启动查询并返回 Promise后续调用返回false而不重新执行。要换变量重新查询需要修改响应式变量 ref/getter 或调用refetch(variables)错误策略errorPolicy为all或ignore时v5 的onError会先于 compat 的onResult触发compat 层用queueMicrotask调整顺序保证与 v4 一致地优先 resolve。小结与延伸阅读useLazyQuery的定位非常明确当变量来自用户动作、无法在挂载时确定时用它替代useQuery一旦load()触发它就完全复用useQuery的响应式机制、缓存策略与查询方法无需学习两套心智模型。其实现简洁优雅——useLazyQuery仅约 40 行核心是useQueryImpl(..., true)加上一个合并变量并等待完成的load()。相关仓库资源实现源码packages/vue-apollo-composable/src/useLazyQuery.ts底层实现packages/vue-apollo-composable/src/useQuery.ts进阶指南packages/docs/advanced/lazy-queries.mdAPI 参考useLazyQuery 函数、Options、Result查询基础packages/docs/data/queries.md、重新获取与轮询对比packages/docs/data/refetching.md、多查询加载状态packages/docs/advanced/loading-states.md赞分享前端GraphQL【免费下载链接】apollo Apollo/GraphQL integration for VueJS项目地址https://gitcode.com/gh_mirrors/apollo2/apollo点击查看免费下载相关推荐Apollo Vue 组合式 API 实战useLazyQuery 按需查询完整指南Apollo Vue 组合式 API 实战useLazyQuery 按需查询完整指南 在 Vue 应用中并非所有 GraphQL 查询都应该在组件挂载时立即前端GraphQLHowToCook 小炒黄牛肉全解湘味大火爆炒的食材量化、工序拆解与嫩滑原理HowToCook 小炒黄牛肉全解湘味大火爆炒的食材量化、工序拆解与嫩滑原理 导读 本篇以程序员做饭指南仓库 HowToCook 中的 小炒黄牛肉菜谱 htt前端GraphQLvue/apollo-composable useLazyQuery Result 接口全解析按需查询的响应式结果对象与 load 生命周期vue/apollo composable useLazyQuery Result 接口全解析按需查询的响应式结果对象与 load 生命周期 本指南围绕 前端GraphQL上一篇如何在3分钟内为Unity游戏安装XUnity.AutoTranslator终极实时翻译插件指南下一篇XUnity Auto TranslatorUnity游戏翻译的终极解决方案让外语游戏无障碍畅玩创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑