
VueUse useUrlSearchParams 指南在 Vue 3 应用中响应式读写 URL 查询参数【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi导读useUrlSearchParams是 VueUse 库中面向浏览器Browser分类的响应式工具它将原生 URLSearchParams 为骨架结合 airi 仓库中真实使用URLSearchParams解析查询串、处理 OAuth 回调、解析桌面悬浮窗参数的源码场景给出从基础用法、路由模式选择、自定义序列化到类型声明与底层原理的完整实战指南。读完你将能够在任何 Vue 3 / Nuxt 3 项目中用几行代码实现「URL 即状态」的共享、分享与可收藏能力。为什么需要响应式 URLSearchParamsURL 查询参数是 Web 应用最轻量的「跨页面、可分享、可收藏」状态载体搜索条件、分页页码、筛选器、来源标识等都可以编码在?foobar中。但直接操作原生 API 非常繁琐——你需要手动get/set/toString()再调用history.replaceState或history.pushState写回地址栏并且每次还要自行处理变化后的 UI 刷新。useUrlSearchParams把这一切收敛为一个响应式对象读取它得到响应式属性赋值即触发写回无需任何手动同步代码。这与 VueUse 团队的设计理念一致——正如 SKILL.md 所强调的优先用 VueUse composable 而非自造轮子以保持代码简洁、可维护且高性能。airi 仓库本身就是这一理念的实践者vueuse/core以catalog:版本约束被引入到 stage-pocket、stage-tamagotchi、stage-web、ui-server-auth 等多个应用与 stage-layouts、stage-pages 等包中数十个页面与 composable 直接import { ... } from vueuse/core。useUrlSearchParams在这些场景中正好可以替代大量手写的查询串解析样板代码。基础用法history 模式默认也是最常见的模式是history即查询参数位于 URL 的?之后。调用方式如下import { useUrlSearchParams } from vueuse/core const params useUrlSearchParams(history) console.log(params.foo) // bar params.foo bar params.vueuse awesome // url updated to ?foobarvueuseawesome要点拆解useUrlSearchParams(history)返回一个响应式对象键值对直接对应查询参数通过params.foo读取当前 URL 中的foo值对params.foo直接赋值后地址栏会自动更新为?foobarvueuseawesome无需手动调用history.replaceState未显式指定 mode 时同样按 history 模式处理mode参数的默认语义即查询串在 search 部分。与原生 URLSearchParams 的对照在useUrlSearchParams内部get对应原生URLSearchParams.getset对应原生URLSearchParams.set。airi 仓库中有大量原生 API 的实战用法可供对照在 window-context.ts 中渲染进程通过new URLSearchParams(search)解析主进程注入的?synced-leaderfalsestage-runtimeminimal查询串读取synced-leader与stage-runtime两个参数并校验合法性最终得到渲染器的leadershipleader-only / follower-only与stageRuntimefull / minimal运行策略——这正是「查询串驱动初始化配置」的典型场景若在 Vue 组件内实现可直接用useUrlSearchParams(history)替换手写解析在 electron-callback.shared.ts 中OAuth 登录回调页用searchParams.get(code)、searchParams.get(state)、searchParams.get(error)等解析授权服务器回传的查询参数并从state中提取端口号与状态值separatorIndex fullState.indexOf(:)其对应的测试用例见 electron-callback.test.ts。两相对照可以发现原生方式适合「一次性解析后不再同步」的场景而useUrlSearchParams的优势在于双向响应式——参数改变立刻反映到响应式对象响应式对象赋值立刻写回 URL。Hash Modehash 路由下的查询参数在使用 hash 模式路由URL 形如#/your/route?...的应用中查询参数位于 hash 片段内部。此时需要把mode显式指定为hashimport { useUrlSearchParams } from vueuse/core const params useUrlSearchParams(hash) params.foo bar params.vueuse awesome // url updated to #/your/route?foobarvueuseawesome使用hash模式后赋值的最终落点从?后移到#内的路由路径之后保证 hash 路由自身的路径结构不被破坏。这非常适合 Vue Router 的createWebHashHistory部署形态例如静态托管平台上的 SPA 应用也适合 airi 中依赖 hash 定位初始化路由的场景——在 window-context.ts 中可以看到resolveInitialRendererRoutePath正是从globalThis.location.hash中切出#后的路由路径#/widgets?sourcetray→/widgets说明该项目的桌面悬浮窗确实以 hash 片段承载路由与来源参数这与hash模式的应用场景完全吻合。Hash Paramshistory 路由 hash 参数还有一种混合形态路由本身使用 history 模式但希望参数放在#之后而非?之后。此时指定mode为hash-paramsimport { useUrlSearchParams } from vueuse/core const params useUrlSearchParams(hash-params) params.foo bar params.vueuse awesome // url updated to /your/route#foobarvueuseawesome这种模式的价值在于避免参数出现在请求行request line中从而减少参数被服务器日志、代理与浏览器历史记录完整记录的暴露面同时仍可利用 hash 变化不会触发整页刷新的特性。airi 的桌面悬浮窗叠加层在判定调试开关时也同时兼顾了 search 与 hash 两处查询串——在 desktop-overlay-polling.ts 中isOverlayPollHeartbeatEnabled同时构造new URLSearchParams(hashQuery)与new URLSearchParams(locationLike.search)并分别读取心跳参数其中 hash 侧正是从location.hash内?之后切出的查询串。可见在实际桌面叠加层场景里参数既可能出现在 search 段也可能出现在 hash 段history/hash/hash-params三种模式恰好覆盖了这些真实分布。自定义序列化函数stringify 选项某些场景下默认的URLSearchParams.toString()序列化结果并不符合需求。useUrlSearchParams提供stringify选项允许完全接管参数的序列化逻辑import { useUrlSearchParams } from vueuse/core // Custom stringify function that removes equal signs for empty values const params useUrlSearchParams(history, { stringify: (params) { return params.toString().replace(/(|$)/g, $1) } }) params.foo params.bar value // url updated to ?foobarvalue instead of ?foobarvalue细节说明stringify接收一个URLSearchParams实例返回序列化后的查询字符串返回的字符串不应包含开头的?或#前缀由 composable 按所选 mode 自动拼接上例通过正则(|$)把空值参数的一并去掉将?foobarvalue压缩为?foobarvalue适用于追求 URL 精简或与后端特殊解析约定对齐的场景。除了stringifyUseUrlSearchParamsOptions还提供以下实用选项详见 useUrlSearchParams.md 的类型声明选项类型默认值作用removeNullishValuesbooleantrue写入时移除值为null/undefined的参数removeFalsyValuesbooleanfalse写入时移除所有 falsy 值、0、false等的参数initialValueT{}初始值URL 中缺失的键以该对象的键兜底writebooleantrue是否自动写回window.history设为false则只读writeModereplace \| pushreplace写回方式replace替换当前历史记录项push压入新历史记录项stringify(params: URLSearchParams) string默认toString()自定义参数序列化函数这里特别值得关注write与writeMode的组合write: true默认时每次赋值都会自动写回地址栏writeMode: replace默认不会产生新的历史记录项适合筛选器、搜索框这类「不希望用户疯狂点返回」的渐进式状态而writeMode: push则让每次变更都成为一条可返回的历史记录适合分页切换等需要支持「返回上一页」的交互。若希望得到纯响应式状态、完全由自己控制写回时机可设置write: false后配合watch手动处理。完整类型声明useUrlSearchParams的完整类型签名如下对应 useUrlSearchParams.md 中的 Type Declarations 一节export type UrlParams Recordstring, string[] | string export interface UseUrlSearchParamsOptionsT extends ConfigurableWindow { /** * default true */ removeNullishValues?: boolean /** * default false */ removeFalsyValues?: boolean /** * default {} */ initialValue?: T /** * Write back to window.history automatically * * default true */ write?: boolean /** * Write mode for window.history when write is enabled * - replace: replace the current history entry * - push: push a new history entry * default replace */ writeMode?: replace | push /** * Custom function to serialize URL parameters * When provided, this function will be used instead of the default URLSearchParams.toString() * param params The URLSearchParams object to serialize * returns The serialized query string (should not include the leading ? or #) */ stringify?: (params: URLSearchParams) string } /** * Reactive URLSearchParams * * see https://vueuse.org/useUrlSearchParams * param mode * param options */ export declare function useUrlSearchParams T extends Recordstring, any UrlParams, ( mode?: history | hash | hash-params, options?: UseUrlSearchParamsOptionsT, ): T几个容易忽视的类型要点返回值是泛型T默认UrlParams即Recordstring, string[] | string因此可以传入自己的接口类型获得完整的类型提示interface Filters { page: string; keyword: string; tag?: string } const params useUrlSearchParamsFilters(history, { initialValue: { page: 1, keyword: } }) // params.page / params.keyword 具备类型推断同一个键可以对应字符串数组string[]用于表达?tagatagb这类重复参数选项接口继承了ConfigurableWindow意味着可传入自定义的window引用如 iframe、测试环境模拟对象这也是它能在 vitest / jsdom 类环境中被可靠测试的接口基础。三种模式的选型建议综合上文给出按路由形态选型的速查你的应用形态推荐 modeURL 示例history 路由createWebHistoryhistory默认https://example.com/search?qairihash 路由createWebHashHistoryhashhttps://example.com/#/search?qairihistory 路由但参数放 hash 内避免进入请求行hash-paramshttps://example.com/search#qairi选型时同时考虑writeMode筛选、搜索、面板状态这类「中间态」建议保持默认的replace分页、步骤切换这类「历史可回溯」的状态可切换为push。在 airi 项目中替换手写解析的落地思路结合前文列举的真实代码可以把 airi 中手写的查询串解析统一收拢到useUrlSearchParams渲染器启动配置window-context.tssynced-leader、stage-runtime的读取与校验可改写为带类型参数的useUrlSearchParams{ synced-leader?: string; stage-runtime?: string }()在watch中做合法性校验同时利用write: false保持启动参数不被误写回OAuth 回调解析electron-callback.shared.ts回调页属于「一次性读取」场景原生URLSearchParams依旧高效若回调页需要把code/state显示在界面上并随用户操作变化则可切换为useUrlSearchParams(history, { write: false })获得响应式呈现悬浮窗调试开关desktop-overlay-polling.ts同时探测 search 与 hash 两处参数的行为本质是对多模式参数的兼容读取可封装成一个同时调用useUrlSearchParams(history)与useUrlSearchParams(hash-params)的组合 composable对外暴露统一的响应式开关。仓库中还有更多URLSearchParams使用点可作类比参考例如 weather-api.ts 中构造天气 API 请求串、sign-in.ts 中透传 OIDC 参数、auth-oidc.ts 中编码 token 请求体——这些属于「输出型」编码通常继续使用原生 API 即可凡是涉及「读 URL → 驱动 UI → 用户交互 → 写回 URL」闭环的场景useUrlSearchParams才是更合适的工具。小结useUrlSearchParams以最小成本把原生URLSearchParams变成 Vue 3 响应式状态三种模式覆盖 history 路由、hash 路由与混合形态removeNullishValues/removeFalsyValues/initialValue提供写入清洗与初始兜底write/writeMode控制写回策略stringify允许自定义序列化。结合 airi 仓库中 window-context.ts、electron-callback.shared.ts 与 desktop-overlay-polling.ts 的真实解析逻辑你可以清晰地判断「何时用手写原生 API、何时交给响应式 composable」从而在 Vue 3 / Nuxt 3 项目中写出更简洁、更可维护的 URL 状态管理代码。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考