ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

如何在 Storybook 插件中读取当前故事数据:addons API 的 getCurrentStoryData() 详解

如何在 Storybook 插件中读取当前故事数据:addons API 的 getCurrentStoryData() 详解 如何在 Storybook 插件中读取当前故事数据addons API 的 getCurrentStoryData() 详解【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook在开发自定义 Storybook 插件Addon时最常见的需求之一就是知道用户当前正在查看哪一条 Story、该 Story 属于哪个组件、携带了哪些参数。官方 Addon API 为此提供了api.getCurrentStoryData()它是storybook/manager-api暴露给所有插件注册入口的便捷方法。本篇指南将以此 API 为核心结合 Storybook 官方文档与仓库源码讲解它的签名、返回数据结构、真实调用案例与底层实现原理帮助你掌握在插件面板、工具栏、快捷操作等场景中读取当前故事元数据的标准姿势。官方文档中的方法定义在官方 Addon API 文档 中getCurrentStoryData被归入 Storybook API 一组定义如下Returns the current storys data, including its ID, kind, name, and parameters.翻译过来即返回当前故事的数据包含其 ID、kind、name故事名与 parameters参数。与之配套的最小示例存放在 storybook-addons-api-getcurrentstorydata.md 中addons.register(my-organisation/my-addon, (api) { // Get data about the currently selected story const storyData api.getCurrentStoryData(); console.log(Current story:, storyData.id, storyData.title); });这个片段虽然简短却包含了使用getCurrentStoryData()的全部关键要素方法只能通过addons.register()注入的api实例调用返回值携带当前故事的多项元数据字段可直接读取使用。先理解上下文addons.register() 与 Addon API要正确使用getCurrentStoryData()需要先了解它的注入方式。根据官方文档Storybook 的 Addon API 被拆成两个独立包职责不同见 addons-api.mdxstorybook/manager-api用于与 Storybook 的 manager UI界面层交互、访问 Storybook APIstorybook/preview-api用于控制与配置插件在预览区的行为。addons.register()是所有插件的入口点它注册一个插件并让你拿到 StorybookAPI 实例见 register 用法片段 与文档 addons.register() 一节。getCurrentStoryData()正是这个 API 实例上的方法因此你只能在注册回调中通过形参api调用它例如在插件面板组件内部通过useStorybookApi()Hook 获得同一实例后再调用。方法签名与返回类型在manager-api的 stories 模块接口中getCurrentStoryData被声明为无参方法见 code/core/src/manager-api/modules/stories.ts/** * Returns the current storys data, including its ID, kind, name, and parameters. * * returns {API_LeafEntry} The current storys data. */ getCurrentStoryData: () API_LeafEntry;注意它的返回类型是API_LeafEntry即故事索引中叶子节点的哈希条目其中Leaf叶子相对分组/组件节点而言代表真正可渲染的一条 Story 或一页 Docs。从官方文档描述与仓库各处的实际使用可以归纳出返回对象至少包含以下常用字段字段含义佐证出处id当前故事在索引中的唯一 ID官方示例直接打印storyData.idtitle当前故事的标题官方示例打印storyData.title文档描述中的 kind 概念name故事名称CSF 中的故事名官方文档描述parameters当前故事的参数对象官方文档描述type条目类型如story、docsroot.tsx 及 url 模块判定importPath该故事对应 CSF 文件的导入路径shortcuts.tssubtype子类型细分如storyurl.test.js文档中提到的 kind在 Storybook 8 的哈希索引体系下对应title组件级标题完整字段细节以API_LeafEntry类型定义为准。典型使用场景打印当前故事把官方片段补全到一个最小可运行插件中可以更直观地看到用法。下面的代码来自 storybook-addons-api-getcurrentstorydata.md 的扩展演示在插件注册阶段读取并输出当前选中的故事// .storybook/my-addon/manager.js import { addons } from storybook/manager-api; addons.register(my-organisation/my-addon, (api) { // Get data about the currently selected story const storyData api.getCurrentStoryData(); if (storyData) { console.log(Current story:, storyData.id, storyData.title); console.log(Parameters:, storyData.parameters); } });实际开发中有两点需要留意判空虽然类型签名标注为API_LeafEntry但在某些状态下可能拿不到数据。仓库内部在调用时普遍做了空值兜底例如 url.ts 中写作fullAPI.getCurrentStoryData() ?? {}shortcuts.ts 中也是直接解构其字段后使用。因此你自己的插件代码也应先判断返回值存在再访问字段。动态性注册回调只在插件加载时执行一次。若想跟踪用户在插件面板激活期间切换 Story 的情况应配合api.on()监听故事导航事件或 React Hook如useStorybookApi()useEffect在每次导航时重新调用而不是依赖一次性读取的结果。阅读源码getCurrentStoryData 是如何实现的想要理解它的行为边界直接看manager-api中 stories 模块的实现见 code/core/src/manager-api/modules/stories.tsgetCurrentStoryData: () { const { storyId, refId } store.getState(); return api.getData(storyId, refId); },实现逻辑可以拆成两步从全局 store 中取出当前选中的故事标识store.getState()返回的 UI 状态里包含storyId当前故事 ID与refId当前所属 ref 的 ID用于多项目 Storybook 组合场景即 composed Storybook。按 ID 在索引中查询对应条目调用同模块的api.getData(storyId, refId)。在 stories 模块中getData负责在本地项目索引或 ref 的索引里按 ID 取回哈希条目其声明见 stories.ts并有配套的resolveStory方法处理索引解析。当 URL 中尚无有效故事 ID、或索引尚未构建完成时查询结果可能为空这就是返回值需要判空的原因。由此可见getCurrentStoryData()本质是当前 URL/路由状态下选中条目的索引查询因此它返回的不仅限于纯 Story也可能是文档页docs 类型返回内容的准确度取决于索引数据是否已准备完毕。官方与生态中的真实调用范例在 Storybook 自己的官方插件与核心代码里getCurrentStoryData()被广泛用于感知当前上下文的功能可作为你设计插件时的参考。核心 HookuseArgs 依赖它读取当前故事manager-api导出的useArgs()Hook 内部就依赖getCurrentStoryData()定位当前故事进而读取、更新其 args见 code/core/src/manager-api/root.tsxexport function useArgs() { const { getCurrentStoryData, updateStoryArgs, resetStoryArgs } useStorybookApi(); const data getCurrentStoryData(); // ...基于 data 读取 args 并封装 setter }这是理解useArgs/useGlobals等官方 Hook 工作原理的钥匙它们都会先调用getCurrentStoryData()拿到叶子条目再读取其中的参数结构。快捷键在编辑器中打开当前故事在键盘快捷键模块中当用户请求打开当前正在查看的故事源码时代码会调用getCurrentStoryData().importPath把该故事对应的 CSF 文件路径交给编辑器打开见 code/core/src/manager-api/modules/shortcuts.tsfile: fullAPI.getCurrentStoryData().importPath,这展示了API_LeafEntry中importPath字段的典型消费方式——实现编辑当前组件/当前 Story类功能时可直接复用。URL 状态同步url 模块在基于当前故事重构查询参数时同样会调用getCurrentStoryData()见 code/core/src/manager-api/modules/url.ts 与 url.ts例如从当前条目中取出id、refId后拼进 URL其单元测试中也大量以 mock 形式验证了这一读取路径见 code/core/src/manager-api/tests/url.test.js。官方插件的实际运用在仓库内的官方插件中也能找到生产级用法onboarding 插件入门引导引导流程需要知道当前正在浏览哪个组件或 Story以决定下一步提示a11y 插件的测试用例在测试中构造 API 上下文验证可访问性检查面板在不同故事间切换时的行为。这些都印证了同一种模式插件 UI 是否响应、校验规则作用于哪条 Story都需要先通过getCurrentStoryData()拿到当前上下文。与其他相邻 API 的配合把getCurrentStoryData()放进整个 Addon API 体系中看它常常与以下方法搭配完整清单见 docs/addons/addons-api.mdxapi.selectStory()/api.selectInCurrentKind()主动切换当前选中故事随后getCurrentStoryData()的结果即随之变化api.on(storyChanged, fn)api.on(eventName, fn)监听故事切换事件在回调中调用getCurrentStoryData()获取最新数据api.getStoryHrefs(storyId)/api.getUrlState()把当前故事转成可分享的 URLapi.getData(storyId, refId)按 ID 精确取数据与取当前选中项形成对照。从源码层级看selectStory负责更新 store 中的storyId而getCurrentStoryData负责从 store 读回storyId并解析数据两者共同构成导航—读取闭环。小结api.getCurrentStoryData()由addons.register()注入的 API 实例提供返回API_LeafEntry类型的当前故事/文档条目返回数据包含id、titlekind、name、parameters、type、importPath等字段足以支撑大多数感知当前上下文的插件功能其实现位于 stories.ts本质是从 store 中读取storyId/refId后经getData()在索引中查询调用时务必处理返回值为空的情况需要实时跟随故事切换时请配合api.on()事件或 React Hooks 使用参考useArgs、快捷键打开当前故事源码、url 状态同步以及 a11y、onboarding 官方插件你可以把同样的模式复用到自己的自定义插件中。核心参考文件方法定义与示例见 docs/addons/addons-api.mdx 与 storybook-addons-api-getcurrentstorydata.md实现与类型见 code/core/src/manager-api/modules/stories.ts、code/core/src/manager-api/modules/stories.tsHook 消费见 code/core/src/manager-api/root.tsx。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表