Storybook Addons API 详解:用 makeDecorator 打造官方风格的 Story Decorator

发布时间:2026/9/9 20:14:30

Storybook Addons API 详解:用 makeDecorator 打造官方风格的 Story Decorator
Storybook Addons API 详解用 makeDecorator 打造官方风格的 Story Decorator【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybookmakeDecorator是 Storybook Preview API 中用于构建Story 装饰器Decorator的工厂函数它把包装 Story这一动作封装成官方 Addon 统一风格的 API既可以在.storybook/preview中注册也能通过故事级parameters按需控制。读完本文你将掌握 makeDecorator 的全部配置项语义、wrapper 回调的调用时机以及如何用它实现withActions这类官方装饰器背后的完整模式并能在自己的 Addon 中直接复用。认识 makeDecorator它解决什么问题Storybook 中Decorator 用于给一个 Story 包裹额外逻辑或 UI例如为组件提供 Provider、注入样式或挂载事件监听。手写装饰器很简单但官方 Addon如 Actions、Backgrounds里的装饰器都遵循一种约定通过参数parameters或显式选项options驱动行为没有配置时静默跳过不打扰用户支持{ yourParameter: { disable: true } }按 Story 关闭。makeDecorator正是把这一套约定固化为标准实现。文档将其定义在 Addon API 的 Preview API 部分——与操作 Manager 界面的storybook/manager-api相对storybook/preview-api用于控制并配置 Addon 在渲染阶段的行为makeDecorator 属于 Decorators API 的一员。在 preview-api/index.ts 中与addons、hooks 等一同从storybook/preview-api对外导出。逐步拆解文档示例storybook-addons-api-makedecorator.md 给出的最小完整示例为import { makeDecorator } from storybook/preview-api; export const withAddonDecorator makeDecorator({ name: withSomething, parameterName: CustomParameter, skipIfNoParametersOrOptions: true, wrapper: (getStory, context, { parameters }) { /* * Write your custom logic here based on the parameters passed in Storybooks stories. * Although not advised, you can also alter the story output based on the parameters. */ return getStory(context); }, });逐项理解import { makeDecorator } from storybook/preview-api工厂函数来自 Preview API。注意它不同于注册面板、工具栏所用的addons后者更常从storybook/manager-api导入因为装饰器运行在preview 渲染进程需要在这里读取参数并包裹 Story 输出。name: withSomethingAddon 装饰器的唯一名称供调试、报错信息定位例如下方底层实现里会用它拼出不允许直接把 story 传进withSomething()的提示。parameterName: CustomParameter约定该装饰器消费的 Storybook 参数名。用户在 Story/CSF 中通过parameters.CustomParameter传入配置。skipIfNoParametersOrOptions: true当用户既没通过parameters传配置、也没在注册时传 options装饰器整体跳过直接渲染原始 Story——这是零配置即透明的关键开关。wrapper真正的装饰逻辑。回调签名包含getStory、context与一个携带options/parameters的对象。makeDecorator 的完整参数语义addons-api.mdx 对参数给出了规范说明与类型定义一一对应配置项类型必填语义namestring是自定义装饰器的唯一标识名称parameterNamestring是设定该 Addon 消费的唯一参数名出现在context.parameters[parameterName]skipIfNoParametersOrOptionsboolean否用户既没通过 decorators 传 options、也没通过 parameters 传配置时不运行装饰器。默认falsewrapperAddon_StoryWrapper是装饰函数接收getStory、context以及options与parameters两者wrapper是核心它的三个入参含义如下getStory一个函数调用它才真正渲染 Story。装饰器里做包裹比如包一层 Provider通常要return getStory(context)否则 Story 内容不会出现。context完整的Addon_StoryContext包含parameters、globals、args、viewMode等故事上下文可读取、也可不推荐地修改后再渲染。第三个对象参数同时携带{ options, parameters }parameters来自故事parameters[parameterName]options来自注册期传入的配置见下文调用形态。底层实现装饰器到底怎么工作makde-decorator 源码把上述语义落成三段逻辑读懂它对排查装饰器为什么不生效非常有用1.parameterName的读取与disable快捷关闭const parameters context.parameters context.parameters[parameterName]; if (parameters parameters.disable) { return storyFn(context); }每次渲染 Story 时工厂从context.parameters里取出该 Addon 命名空间下的参数。文档特别提醒如果某个 Story 的parameters形如{ CustomParameter: { disable: true } }装饰器将不会被调用直接透传 Story。这正是各框架按 Story 关闭 Addon 效果的通用机制。2.skipIfNoParametersOrOptions的空转短路if (skipIfNoParametersOrOptions !options !parameters) { return storyFn(context); }同时满足没有注册期 options与没有参数配置时才跳过。注意它与disable的区别disable是用户显式关闭短路条件是参数对象带disable: true而 skip 是无任何配置时的默认透明。3. 转发到wrapperreturn wrapper(storyFn, context, { options, parameters });两者都通过后才把配置对象合并交给你的wrapper执行。三种调用形态与封装返回makeDecorator 返回的decorator支持多种用法源码第 68-89 行通过参数形态判断兼容了它们直接注册无 optionsdecorator首参是函数时等价于.addDecorator(decorator)——decorator()(...args)。带单个/多个 options 注册decorator(options)或decorator(opt1, opt2, ...)返回一个真正可用的装饰器这些 options 会被作为options传给 wrapper允许展开多个参数测试用例覆盖了单值、对象、多值、多值与对象混合四类形态。禁止把 Story 直接传给装饰器当decorator(options)(story)里内层调用仅一个参数时直接抛出错误提示应改走addDecorator(name) 参数通道Passing stories directly into ${name}() is not allowed, instead use addDecorator(${name}) and pass options with the ${parameterName} parameter也就是说Addon 装饰器的配置来源有两条合法通道注册期经 optionsdecorator(opts)传入运行期经故事parameters[parameterName]传入二者会在 wrapper 中合并。官方真实范例withActions 是怎么写的Storybook 仓库内 actions 装饰器 本身就是 makeDecorator 的教科书级用法export const withActions: T extends Renderer(storyFn: PartialStoryFnT) T[storyResult] makeDecorator({ name: withActions, parameterName: PARAM_KEY, skipIfNoParametersOrOptions: true, wrapper: (getStory, context, { parameters }) { if (parameters?.handles) { applyEventHandlers(actions, ...parameters.handles); } return getStory(context); }, });观察要点PARAM_KEY来自./constants.ts承载parameterName而CFS/story 中的parameters.handles配置恰好落在wrapper的parameters上——与本文的 snippet 是同构的。skipIfNoParametersOrOptions: true保证用户没有配置handles时该装饰器不做任何事、不留性能与行为开销。wrapper 内部执行副作用applyEventHandlers监听事件后仍然return getStory(context)把渲染交给 Storybook。由此可得一个放之四海皆准的 makeDecorator 工作流读取参数 → 副作用/包裹逻辑 → 调用 getStory 返回渲染。官方 Backgrounds、Themes 等装饰器也遵循同一工厂与参数通道参考 writing-stories/decorators.mdx、writing-stories/parameters.mdx 中关于如何以parameters配置装饰器的通用约定。从零编写一个完整 Addon 装饰器把上述知识串联成一个完整流程你只需要三步第一步在 Addon 中导出装饰器// my-addon/src/decorator.ts import { makeDecorator } from storybook/preview-api; export interface CustomParameters { /** 传给组件的背景色 */ backgroundColor?: string; /** 是否在调试台打印参数 */ debug?: boolean; } export const withCustom makeDecorator({ name: withCustom, parameterName: customParameter, skipIfNoParametersOrOptions: true, wrapper: (getStory, context, { parameters, options }) { const { backgroundColor options?.defaultColor, debug } parameters ?? {}; if (debug) { console.log([withCustom] rendering story, context.title, context.name, parameters); } // 示例包一层带背景的容器 // 需配合渲染框架能力实现React 示例 return getStory(context); }, });第二步注册到预览// .storybook/preview.js import { withCustom } from my-addon/src/decorator; export const decorators [withCustom];第三步按 Story 传参数控制// Button.stories.js export default { title: Button, parameters: { customParameter: { backgroundColor: #ff4785, debug: true }, // 打开该装饰器 }, };想全局关闭某 Addonparameters: { customParameter: { disable: true } }此时 wrapper 根本不会运行。想不做任何配置也零影响保持skipIfNoParametersOrOptions: true。用仓库测试验证行为契约makeDecorator 的语义不是文档口头约定而是被 make-decorator.test.ts 用 Vitest 逐一锁定的parameters 透传上下文带parameters: { test: test-val }时wrapper 收到{ parameters: test-val }第 24-34 行注册期 options 透传decorator(options)后 wrapper 收到{ options: test-val }且单值、对象、多值、多值混对象四种形态都成立第 36-92 行options 与 parameters 并存两者同时存在时合并传给 wrapper第 94-108 行双空透传都不存在时 wrapper 收到空对象{}第 110-120 行skip 语义skipIfNoParametersOrOptions: true且配置全空时 wrapper 不被调用、Story 被直接执行第 122-138 行disable 语义parameters: { test: { disable: true } }时同样跳过 wrapper、直通 Story第 140-156 行错误防护decorator(options)(story)这种把 story 直接当参数传入的写法会抛出/not allowed/错误第 158-168 行。你可以把无配置透明、disable 优先、options/parameters 双通道合并、禁止直传 story这四条当作 makeDecorator 的行为契约——你的 Addon 只要遵循它们就能与官方 Addon 在外观与手感上完全一致。补充与 Addon API 其他部分的关系makeDecorator 通常不是 Addon 的全部。一个完整 Addon 往往还包含manager 侧面板、工具栏等 UI 通过addons.add()/addons.register()注册见 addons-api.mdxpreview 侧装饰器通过 makeDecorator 参与渲染二者通信经getChannel()获得 EventEmitter 兼容的 channel 收发事件见 addons-api.mdx。makeDecorator只负责 preview 侧包裹 Story这件单一职责这也是它容易被单独理解、单独测试的原因——在 preview-api/index.ts 中它与 hooks 等共同构成 Preview API 的 Decorators/Hooks 出口属于现代 CSF 推荐写法之外、为官方风格 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),仅供参考

相关新闻

用Excel驱动C#自动化测试平台:告别写死用例,轻松维护回归测试

用Excel驱动C#自动化测试平台:告别写死用例,轻松维护回归测试

2026/9/9 20:04:29

如果你在维护一个需要反复回归的测试项目,应该能体会到那种痛:用例一多,断言写死在代码里,功能稍微调整一下就要重新编译、重新部署,测试人员想改一条数据还得找你排队。我前段时间正好把一套用C#写的自动化测试平台完…

Power Platform与Dynamics 365集成实战:从商机到售后全链路自动化

Power Platform与Dynamics 365集成实战:从商机到售后全链路自动化

2026/9/9 20:04:29

1. 项目从哪来:一个典型的业务断点我先把这个项目的背景讲清楚。去年我在一家做工业设备销售的中型企业做数字化转型咨询,客户的核心痛点非常典型:销售部门用一套Excel加邮件在管商机,服务部门用另一套工单系统在处理售后&#xf…

OpenMontage 数学动画实战:用 ManimGL 构建 3D 视差星场(Parallax Starfield)教学动画

OpenMontage 数学动画实战:用 ManimGL 构建 3D 视差星场(Parallax Starfield)教学动画

2026/9/9 20:04:29

OpenMontage 数学动画实战:用 ManimGL 构建 3D 视差星场(Parallax Starfield)教学动画 【免费下载链接】OpenMontage Worlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and…

冻土水热力三场耦合仿真:从物理机制到COMSOL建模全解析

冻土水热力三场耦合仿真:从物理机制到COMSOL建模全解析

2026/9/9 20:54:32

1. 为什么冻土仿真必须是“三场耦合”:先理解水、热、力的物理纠缠1.1 相变是三场耦合的发动机很多刚接触冻土模拟的朋友第一反应是:温度场会算,渗流场会算,应力场也会算,那我把三个物理场堆到一起不就是冻土模型了吗&…

Milvus 主键索引(Primary Key Index)设计解析:BBhash + Value Array 支撑十亿级跨 Segment 主键精确查找

Milvus 主键索引(Primary Key Index)设计解析:BBhash + Value Array 支撑十亿级跨 Segment 主键精确查找

2026/9/9 20:54:32

Milvus 主键索引(Primary Key Index)设计解析:BBhash Value Array 支撑十亿级跨 Segment 主键精确查找 【免费下载链接】milvus Milvus is a high-performance, cloud-native vector database built for scalable vector ANN search 项目地…

claude-howto 实战:用 doc-generator 技能从源码自动生成高质量 API 文档

claude-howto 实战:用 doc-generator 技能从源码自动生成高质量 API 文档

2026/9/9 20:54:32

claude-howto 实战:用 doc-generator 技能从源码自动生成高质量 API 文档 【免费下载链接】claude-howto A visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value. 项…

在 goose 中接入 Laminar 实现 Agent 可观测性:OTLP 导出配置与 Trace 分析实战

在 goose 中接入 Laminar 实现 Agent 可观测性:OTLP 导出配置与 Trace 分析实战

2026/9/9 20:54:32

在 goose 中接入 Laminar 实现 Agent 可观测性:OTLP 导出配置与 Trace 分析实战 【免费下载链接】goose an open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM 项目地址: https://gitcode.co…

TiDB Lock View 锁视图设计解析:基于 information_schema 的事务锁等待、锁竞争与死锁诊断

TiDB Lock View 锁视图设计解析:基于 information_schema 的事务锁等待、锁竞争与死锁诊断

2026/9/9 20:54:32

TiDB Lock View 锁视图设计解析:基于 information_schema 的事务锁等待、锁竞争与死锁诊断 【免费下载链接】tidb TiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vecto…

植物大战僵尸Android源码2:从环境搭建到二次开发的完整实践指南

植物大战僵尸Android源码2:从环境搭建到二次开发的完整实践指南

2026/9/9 20:44:31

简介:植物大战僵尸Android源码2是一份面向具有一定Android基础的游戏开发者与进阶学习者的塔防游戏完整工程,聚焦于游戏整体架构、场景切换和角色AI的设计实践。压缩包共包含173个文件,其中以120张PNG图片素材、20个Java源码文件、13张JPG贴图…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/9 1:14:29

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/8 4:55:53

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/8 22:37:26

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

2026/9/9 0:03:36

简介:面向毕业设计场景的PyQt5扩散模型图像恢复项目,提供完整Python源码与项目说明,适合图像处理、深度学习方向的高年级本科生与研究生参考。项目在模块设计上覆盖图像处理、扩散模型、参数配置、用户界面与结果评估五部分,具体涉…

开关电源环路裕量测试实战:相位裕量与增益裕量详解

开关电源环路裕量测试实战:相位裕量与增益裕量详解

2026/9/9 0:03:36

1. 项目概述:为什么环路裕量测试是电子工程师绕不开的“体检项目”“从零开始的电子工程师生活(6)——环路裕量测试”,这个标题一出来,老电源工程师可能已经下意识摸了摸示波器探头,新同事则大概率在想&…

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

2026/9/9 0:03:36

拆开市面上不同价位的定时插座,你会发现一个有意思的现象:有的里面躺着一颗黑色的软封装芯片,丝印都看不清;有的则是一块小小的蓝色或绿色PCB,上面赫然印着STM8或者STC的字样。同样叫"定时插座",…

远程协作的工作台整理

远程协作的工作台整理

2026/9/9 16:28:52

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…