
Storybook 跨框架 Props 声明实践一份自动生成 argTypes 与 Controls 的速查指南【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook为什么改了组件的 propsControls 面板却不更新、Docs 里的参数描述还是空的因为在 Storybook 里component一旦声明docgen 就会解析你的组件源码把 Props 类型与 JSDoc 注释转换成argTypes——类型决定控件形态注释变成面板描述默认值写进参数表格。这份指南覆盖 React、Angular、Vue、Svelte、Web ComponentsLit五类跨框架组件类型写法帮你把Props 声明 注释一次写到位。先讲透数据流你的声明如何变成 argTypes 结论先行docgen 的输入是组件源码本身输出是结构化的argTypes。整条链路是*.stories.*里声明componentdocgen 据此定位组件文件各框架的解析器React 用 react-docgen、Angular 用 Compodoc、Vue 用vue-docgen-api、Web Components 解析 JSDoc把类型、默认值、注释抽出来结果合并成argTypesControls 与 Docs 的 ArgsTable 直接按它渲染。仓库里 storybook-generated-argtypes.md 片段给出了这段推导的产物长什么样const argTypes { label: { name: label, type: { name: string, required: false }, defaultValue: Hello, description: demo description, table: { type: { summary: string }, defaultValue: { summary: Hello }, }, control: { type: text, }, }, };对照组件源码字段来源一一对应type.name: string来自你在源码里写的类型PropTypes.string、TS 字段、type: String、propertydescription来自字段上方的 JSDoc 注释defaultValue/table.defaultValue来自默认值写法解构初值、default、字段初始值control.type: text由类型推断——布尔渲染成开关、字符串渲染成文本框这一步完全不用你手写。所以声明即文档你不需要在 stories 里为每个 prop 手工补argTypes组件写清楚面板自己长出来。仓库内各框架的解析链路可作佐证React 侧 code/frameworks/react-vite 依赖react-docgenVue 侧 code/renderers/vue3/src/docgen 用vue-docgen-api转换__docgenInfoAngular 侧则由 Compodoc 生成元数据。逐框架实战声明位置、类型来源、默认值与注释位置以下统一按四要素拆解声明位置 / 类型来源 / 默认值写法 / 注释位置。代码均取自 button-component-with-proptypes.md 片段是最小可运行骨架。ReactpropTypes 或 interface 配 JSDoc补齐运行期与编译期类型声明位置Button.propTypesJS或ButtonPropsinterfaceTS类型来源PropTypes.*/ TS 类型默认值JS 版无由调用方提供TS 版走解构初值注释位置字段上方 JSDoc。import React from react; import PropTypes from prop-types; export function Button({ isDisabled, content }) { return ( button typebutton disabled{isDisabled} {content} /button ); } Button.propTypes { /** Checks if the button should be disabled */ isDisabled: PropTypes.bool.isRequired, /** The display content of the button */ content: PropTypes.string.isRequired, };TS 版本把类型与默认值都收进 interface 和解构参数export interface ButtonProps { /** * Checks if the button should be disabled */ isDisabled: boolean; /** The display content of the button */ content: string; } export const Button: React.FCButtonProps ({ isDisabled false, content }) { return ( button typebutton disabled{isDisabled} {content} /button ); };要点isRequired表达必填缺失时开发环境控制台告警注释块紧贴字段名react-docgen 会把它提取为argTypes.description直接显示在 ArgsTable 和 Controls 里TS 版的解构默认值 false/ 会被 docgen 读成defaultValue缺省时按钮仍可点击。AngularInput()字段就是 Props注释写在装饰器上方声明位置类中Input()字段类型来源字段的 TS 类型默认值字段初值示例未给注释位置字段上方 JSDoc。import { Component, Input } from angular/core; Component({ selector: my-button, template: button typebutton [disabled]isDisabled {{ content }} /button, styleUrls: [./button.css], }) export class ButtonComponent { /** * Checks if the button should be disabled */ Input() isDisabled: boolean; /** The display content of the button */ Input() content: string; }要点[disabled]isDisabled属性绑定布尔开关{{ content }}插值渲染文本想让禁用变成可选且有默认值给字段赋初值即可如isDisabled false——这是 Angular 里表达可选 默认值的常规写法属性上方加requiredJSDoc 标记可表达必填语义见 button-implementation.md 的 Angular 版本。Vue 3props 选项里同时声明类型、默认值与必填声明位置props对象JS或defineComponent({ props })TS类型来源type: Boolean / String默认值default注释位置prop 项上方。template button typebutton :disabledisDisabled{{ label }}/button /template script export default { name: button, props: { /** * Checks if the button should be disabled */ isDisabled: { type: Boolean, default: false, required: true, }, /** * The display label of the button */ label: { type: String, default: One, required: true, }, }, }; /scriptTS 版本用defineComponent包住选项对象setup(props)即获得完整类型推导结构不变langts脚本块内。要点三要素type/default/required都会被vue-docgen-api转换进argTypes——必填会体现在type.requireddefault进入table.defaultValue必填 默认值并存时运行期以默认值兜底两者选一表达更清晰避免评审时被追问注意本片段用label而非 React 版的content展示文案同一组件在不同框架片段里字段命名可以不同跨框架对照时留意。Svelteexport let即 Propsrequired标记补必填语义声明位置script中export let变量类型来源Svelte 编译器 JSDoc默认值变量初始值注释位置变量上方 JSDoc。script /** * A Button Component * component */ /** * Disable the button * required */ export let disabled false; /** * Button content * required */ export let content ; /script button typebutton {disabled}{content}/button要点export let disabled false一行同时声明属性与默认值模板里{disabled}是disabled{disabled}的简写required是约定标记表达语义上必须提供供 Svelte CSF / docgen 工具解析属性名是disabled而非其他框架的isDisabled——同一语义在不同框架命名并不统一写文档时以实际字段为准。Web ComponentsLit类上方 JSDoc static properties或property()声明位置static get properties()JS或property()字段TS类型来源type: String/Boolean或 TS 类型默认值构造函数赋值或字段初值注释位置类上方 JSDoc 块逐属性用prop。import { LitElement, html } from lit; /** * prop {string} content - The display label of the button * prop {boolean} isDisabled - Checks if the button should be disabled * summary This is a custom button element * tag custom-button */ export class CustomButton extends LitElement { static get properties() { return { content: { type: String }, isDisabled: { type: Boolean }, }; } constructor() { super(); this.content One; this.isDisabled false; } render() { return html button typebutton ?disabled${this.isDisabled}${this.content}/button ; } } customElements.define(custom-button, CustomButton);TS 版把声明压缩进装饰器import { LitElement, html } from lit; import { customElement, property } from lit/decorators.js; /** * prop {string} content - The display label of the button * prop {boolean} isDisabled - Checks if the button should be disabled * summary This is a custom button element * tag custom-button */ customElement(custom-button) export class CustomButton extends LitElement { property() content?: string One; property() isDisabled?: boolean false; render() { return html button typebutton ?disabled${this.isDisabled}${this.content}/button ; } }要点类上方prop描述是 web-components docgen 的唯一输入——漏写它就漏掉参数描述tag与customElements.define/customElement共同确定注册名stories 里component要用同名字符串引用?disabled${...}是 Lit 的布尔属性绑定语法与 React 的disabled{...}语义相同。一图速查六大框架 Props 声明对照表组件名框架 / 版本声明方式类型来源默认值写法必填表达ButtonReact (JS)Button.propTypesPropTypes.bool/string无调用方提供.isRequiredButtonReact (TS)ButtonPropsinterfaceTS 类型 React.FC泛型解构初值 false/ 字段不加?my-buttonAngularInput()字段字段 TS 类型字段初值可选JSDocrequiredbuttonVue 3 (JS)props选项type: Boolean/Stringdefault: false / Onerequired: truebuttonVue 3 (TS)defineComponent的props运行时type TS 推导default: false / Onerequired: trueButtonSvelteexport let编译器 JSDoc false/ JSDocrequiredcustom-buttonWeb Components (JS)static get properties()type: String/Boolean构造函数赋值默认值约定custom-buttonWeb Components (TS)property()字段Lit 装饰器 TS 类型字段初值默认值约定共性规律三条注释位置各家不同但最终都落在argTypes.description类型与默认值共同决定控件形态和参数表必填语义的表达手段各异但 JSDocrequired是跨框架最通用的软方案。 排查与自查docgen 没生效时的四条实操声明写对了却不生效多数卡在这几处先确认 meta 里component指向正确。Vue 的 docgen 会主动校验检测不到组件时报 Specify meta.component追踪不到导入时报 No component file found。Web Components 更特殊——component必须是注册后的元素名字符串如custom-button传类引用无效。核对注释是否贴在正确的那一行。React 的注释要写在propTypes字段上方写在函数参数解构旁无效Web Components 的prop必须整块放在类声明上方而非字段旁Svelte 的注释紧贴export let。位置错一行描述就丢失。检查类型与期望控件是否一致。布尔声明成String、或 Lit 里漏了type: BooleanControls 会从开关退化成文本框/复选框行为异常。对照 Controls 文档 里的渲染规则逐一核对。区分没生成和没覆盖。如果argTypes缺字段是声明/docgen 问题如果字段在但描述或默认值不对检查是否被 meta 里手写的argTypes覆盖、或片段中required: true与default并存导致语义混淆。Svelte 项目另需确认已接入storybook/addon-svelte-csf否则required等标记无人解析。自查清单一句话版component 指对了吗注释贴对行了吗类型写对了吗手写 argTypes 是否覆盖了自动推导下一步在*.stories里声明component让元数据与 Story 挂钩组件声明完成后最小 meta 只需把component指过去docgen 才会开始工作// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc. import type { Meta } from storybook/your-framework; import { Button } from ./Button; const meta { component: Button, parameters: { actions: { argTypesRegex: ^on.* } }, } satisfies Metatypeof Button; export default meta;parameters: { actions: { argTypesRegex: ^on.* } }会把onClick这类以on开头的属性自动挂上 Actions 记录详见 actions.mdx组件的args如何与上面生成的argTypes配合、参数如何进入每个 Story见 args.mdx更多跨框架按钮示例都沉淀在 可复用片段目录如 button-story.md。一句话收尾把 Props 类型写准、把 JSDoc 写全Storybook 的 Controls、Docs 与测试能力随之自动生效——这不是文档洁癖而是跨框架组件开发里最划算的一步投入。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考