Storybook Addon API 深度解析:使用getUrlState()读取与重建应用 URL 状态
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
本文基于 Storybook 仓库中的 addon 开发文档与源码,系统讲解 addon 注册回调中获取的
api.getUrlState()方法。你将理解它返回哪些字段、如何在自定义 addon 中读取当前 URL 状态(含当前 story、viewMode 与自定义 query 参数),并掌握它与setQueryParams、getQueryParam、applyQueryParams等兄弟 API 配合构建可分享链接的完整思路。
一、getUrlState()是什么
在开发 Storybook addon 时,你通常需要在 manager(管理界面)侧读取"当前应用处于什么状态":正在展示哪一个 story、处于story还是docs视图模式、URL 上挂了哪些自定义查询参数、以及完整的 URL 是什么。
api.getUrlState()正是为此提供的 API。官方文档将它的签名写作api.getUrlState(overrideParams),语义为"获取应用 URL 状态,包括任何被覆盖的或自定义的参数值"。它可以在addons.register()的注册回调中被调用,因为该回调的第二个参数就是 addon 可用的 manager API 对象。
在 docs/addons/addons-api.mdx 的 "Storybook API" 小节中,它被放在setQueryParams/getQueryParam之后、getStoryHrefs之前,共同构成一套"读写 URL 状态"的工具集。
二、最小用法示例
原文档 storybook-addons-api-geturlstate.md 给出的标准示例位于 addon 的 manager 入口文件中:
// my-addon/src/manager.js|ts addons.register('my-organisation/my-addon', (api) => { const href = api.getUrlState({ selectedKind: 'kind', selectedStory: 'story', }).url; });示例拆解:
addons.register('my-organisation/my-addon', cb):注册一个 addon,名称需保持全局唯一(习惯使用组织名/addon名的命名空间形式)。- 回调参数
api:manager 侧完整 API,getUrlState是其中的方法之一。 getUrlState(...).url:取回结果的url字段——即当前 Storybook 应用在地址栏中的完整 URL 字符串。
需要说明的是:文档示例中传入的selectedKind/selectedStory属于早期(v5 时代)Storybook 以selectedKind=...&selectedStory=...形式定位 story 时的遗留参数写法,当前文档保留该片段用于展示"以覆盖参数请求 URL 状态"这一历史接口形态;而在现代 Storybook 中,story 的定位已统一为?path=/story/...。因此对当前版本来说,最稳妥、最有价值的调用方式是直接读取返回值:
// my-addon/src/manager.js|ts addons.register('my-organisation/my-addon', (api) => { // 获取完整 URL 状态 const state = api.getUrlState(); // 取完整 URL:https://host/path/?path=/story/button--primary&args=label:Hello const href = state.url; // 其余字段按需使用(见下文字段说明) const { path, viewMode, storyId, queryParams, hash } = state; });三、返回值的字段结构
从当前仓库源码 code/core/src/manager-api/modules/url.ts 中SubAPI接口的类型声明可以看到,getUrlState返回对象包含以下字段:
| 字段 | 类型 | 含义 | 示例 |
|---|---|---|---|
url | string | 当前应用完整 URL | /index.html?path=/story/button--primary&args=label:Hello |
path | string | URL 中的路径段(含/story/前缀的 story 定位) | /story/button--primary |
viewMode | string \| undefined | 当前视图模式 | 'story'、'docs' |
storyId | string \| undefined | 当前 story 的 ID | 'button--primary' |
queryParams | QueryParams | 自定义查询参数(不含布局类参数,见下文) | { args: 'label:Hello', globals: 'theme:light' } |
hash | string | 当前 location 的 hash | '' |
类型声明原样如下:
getUrlState: () => { queryParams: QueryParams; path: string; hash: string; viewMode?: string; storyId?: string; url: string; };用途提示:
url:最适合用来拼出"当前所处状态"的可分享/可回退链接;path+hash+queryParams:在实现"追加一个参数后原地跳转"这类逻辑时,可以先把状态拆开、合并新参数、再交给导航方法;storyId/viewMode:addon 需要感知用户正在看哪个 story、处于文档还是 story 视图时使用。
四、源码实现:URL 状态从哪来
4.1 实现本体
getUrlState的实现位于 code/core/src/manager-api/modules/url.ts,它并不自行解析 location,而是直接读取 manager 的全局 store 状态:
getUrlState() { const { location, path, customQueryParams, storyId, url, viewMode } = store.getState(); return { path, hash: location?.hash ?? '', queryParams: customQueryParams, storyId, url, viewMode, }; },这意味着getUrlState()返回的永远是当前 store 中已被同步过的、真实的 URL 状态,而不是临时计算结果。它依赖的store.getState()快照由 URL 模块在初始化时(initialUrlSupport)以及每次导航时统一维护,因此不同调用点拿到的结果彼此一致。
4.2 自定义 query 参数如何界定
queryParams(即 store 中的customQueryParams)来源于地址栏查询串,但有一类"布局/导航参数"会被排除在外。源码通过白名单常量实现这一过滤(code/core/src/manager-api/modules/url.ts):
// URL query params the manager consumes for layout/navigation. // Everything else is a custom param passed through to the preview iframe. const LAYOUT_QUERY_PARAM_KEYS = ['full', 'panel', 'nav', 'shortcuts', 'addonPanel', 'tabs', 'path']; export const getCustomQueryParams = (location) => omit(queryFromLocation(location), LAYOUT_QUERY_PARAM_KEYS);也就是说:full、panel、nav、shortcuts、addonPanel、tabs、path这些由 manager 消费的键不会出现在getUrlState().queryParams中;而像args、globals以及 addon 通过setQueryParams写入的自定义参数则会保留,并被透传到 preview iframe 使用。
4.3 与 URL 解析/构建基础设施的关系
模块顶层还引入并复用了 router 工具queryFromLocation与buildNavigationUrl(code/core/src/manager-api/modules/url.ts、lib/url.ts 中的 buildNavigationUrl),URL 模块整体是这些底层工具之上的一层"状态化封装"——addon 开发者无需关心 URL 语法细节,只需通过 API 读写。
五、与相关 API 的组合使用
getUrlState所在的 URL 模块同时暴露了一组配套 API(见 code/core/src/manager-api/modules/url.ts 的SubAPI实现),它们共同覆盖"读状态、改参数、发起导航"的完整闭环:
| API | 作用 | 关键实现细节 |
|---|---|---|
getQueryParam(key) | 读取单个自定义查询参数的值 | 直接读store.getState().customQueryParams[key],不存在返回undefined |
setQueryParams(input) | 写入/更新查询参数(临时存储),参数置null/undefined表示删除 | 与原值deepEqual相同则跳过,变化后写 store 并通过 channel 广播UPDATE_QUERY_PARAMS事件 |
applyQueryParams(input, options) | 设置参数并触发导航 | 内部先调getUrlState()取回path/hash/queryParams,合并后导航 |
navigateUrl(url, options) | 直接导航到指定 URL | 以plain: true方式交给 router |
getStoryHrefs(storyId, options?) | 为某个 story 生成 manager/preview 两个链接 | 支持base、inheritArgs、inheritGlobals、refId、viewMode等选项 |
一个典型的"读出当前状态 → 加上自定义参数 → 生成新链接"示例:
// my-addon/src/manager.js|ts import { addons } from 'storybook/manager-api'; addons.register('my-organisation/my-addon', (api) => { const state = api.getUrlState(); // 1) 单独读取某个参数 const currentHighlight = api.getQueryParam('highlighted'); // 2) 写入参数并触发一次导航(自动合并当前位置与已有参数) api.applyQueryParams({ highlighted: currentHighlight === 'true' ? null : 'true' }); // 3) 由当前完整 URL 状态构造可分享链接(例如加上跟踪标记) const { url } = api.getUrlState(); const shareable = `${url}${url.includes('?') ? '&' : '?'}utm_source=my-addon`; console.log(shareable); });六、使用注意点
- 运行环境:
getUrlState属于 manager 侧 API,只能在 addon 的 manager 入口(如my-addon/src/manager.js|ts)中使用,不要与 preview(iframe)侧 API 混用。官方在 docs/addons/addons-api.mdx 中将其归入addons.register回调提供的 API 之列。 - 参数语义:文档标题中的
overrideParams与示例里的selectedKind/selectedStory反映的是历史版本"用 kind/story 覆盖 URL 状态"的用法;从本仓库当前SubAPI类型声明与实现看,方法调用时不读取参数,直接返回 store 中同步好的完整状态。若你的 addon 需要兼容文档示例写法,应以"读取.url字段"为可靠基线。 - 返回值是快照:
getUrlState()返回的是调用时刻的 URL 状态副本。若需要在用户每次切换 story 后都拿到最新值,应配合api.on(...)之类的事件订阅在回调中重新调用。 - 自定义参数范围:
queryParams中不含full/panel/nav/shortcuts/addonPanel/tabs/path等布局键,不要期望从该字段拿到这七类参数。
七、延伸阅读
- 完整的 addon API 索引见 docs/addons/addons-api.mdx,其中
getUrlState前后相邻的setQueryParams、getQueryParam、getStoryHrefs均配套有独立 snippet,可对照阅读:- storybook-addons-api-getqueryparam.md
- storybook-addons-api-setqueryparams.md
- storybook-addons-api-disablequeryparams.md
- URL 状态模块的核心源码位于 code/core/src/manager-api/modules/url.ts(类型声明与实现分别在
SubAPI与init导出中),URL 解析/构建工具在 code/core/src/manager-api/lib/url.ts。
小结:getUrlState()是 addon 在 manager 侧获取"当前 Storybook 到底是什么状态"的标准入口。理解它返回的六个字段、明白queryParams与布局参数的边界、再配合setQueryParams/applyQueryParams/getStoryHrefs这一组 URL 读写工具,你就可以在 addon 中可靠地实现"读取 → 改写 → 导航/分享"的完整链路。
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考