Storybook Vue 3 Docs 实战指南:从 addon-docs 安装到 Docgen 提取与 MDX 长文文档
【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook
本文基于 Storybook 仓库内 Vue 3 框架的官方文档页(code/addons/docs/docs/frameworks/VUE3.md),系统讲解如何在 Vue 3 项目中配置 Storybook Docs:包括@storybook/addon-docs的安装与注册、vueDocgenOptions预设选项、Props 表格的生成链路、MDX 长文文档写法以及 Inline Stories 渲染控制。读完后你不仅能完成 Vue 3 项目的 Docs 落地配置,还能从源码层面理解 Storybook 是如何提取 Vue 组件元信息(props / events / slots)的。
一、Docs 在 Vue 3 项目中的定位
Storybook Docs 会将你的 Story 转换为结构化的组件文档。针对 Vue 3,它提供两种文档形态:
- DocsPage:自动生成的文档页,零配置聚合组件的 Story、描述、docgen 注释、Props 表格和代码示例,展示在 Storybook UI 的
Docs标签页中(完整参考见 DocsPage); - MDX:以 Markdown 写长文文档,并内联嵌入 Story、Props 表格等文档组件(完整参考见 MDX)。
两者关系可以理解为:DocsPage 是"开箱即用的默认值",MDX 是"完全可控的自定义"。Docs Addon 的总览文档见 code/addons/docs/README.md。
二、安装
第一步,安装 Docs Addon 包(注意保持所有@storybook/*包版本一致):
yarn add -D @storybook/addon-docs第二步,在.storybook/main.js的addons中注册:
export default { addons: ['@storybook/addon-docs'], };安装完成后,所有 Story 会自动获得 DocsPage,在 Storybook UI 中点击Docs标签页即可查看,无需额外配置。
三、Preset 选项:vueDocgenOptions
addon-docs的 Vue 预设暴露了一个配置项,用于配置vue-docgen-api——一个从 Vue 组件中提取 props / events / slots 信息的工具。当你的项目使用了路径别名(如@/指向src),docgen 解析器需要知道别名映射,此时就需要传入vueDocgenOptions:
export default { addons: [ { name: '@storybook/addon-docs', options: { vueDocgenOptions: { alias: { '@': path.resolve(process.cwd(), 'src'), }, }, }, }, ], };vueDocgenOptions是一个透传给vue-docgen-api的选项对象,完整可用的字段以vue-docgen-api官方文档为准。典型场景:monorepo 中 Storybook 位于子包目录、组件通过@/components别名导入时,不配置alias会导致 docgen 解析不到组件,Props 表格为空。
源码视角:Vue 文档提取引擎的当前实现
原文档描述的是vue-docgen-api的直连配置。而从当前仓库的源码结构看,Vue 3 的 docgen 提取链路已经演进:code/renderers/vue3/src/preset.ts 中导出了experimental_vueDocgenEngine预设,它按插件懒加载两个提取引擎:
/** Docgen extraction engines, keyed by plugin. Each loads lazily so a project only pays for the one it uses. */ export const experimental_vueDocgenEngine = async () => ({ componentMeta: () => import('./docgen/component-meta.ts'), vueDocgenApi: () => import('./docgen/vue-docgen-api.ts'), });其中:
- code/renderers/vue3/src/docgen/component-meta.ts 是基于
vue-component-meta(Volar 语言服务内核)的主提取路径,会优先使用项目根目录的tsconfig.json创建 checker(createVueComponentMetaChecker),以支持别名解析等;若tsconfig.json使用了references则回退到默认 checker。它还负责一系列"去噪"与补全:过滤空 meta、剔除嵌套 schema 以减小storybook build产物体积、合并defineEmits/ 模板 slot 的信息缺口; - code/renderers/vue3/src/docgen/vue-docgen-api.ts 则是对
vue-docgen-api.parse的兼容封装,目前作为补充手段:当 Volar 提取出 events 或发现模板<slot>缺口时,会调用vue-docgen-api的parseMulti补齐事件描述、运行时defineEmits事件以及 Options API 组件的模板 slot(见applyVueDocgenApiTempFixes)。
也就是说,原文档中的vueDocgenOptions依然有效,但其底层信息源已从"vue-docgen-loader 单一依赖"演化为"vue-component-meta 为主、vue-docgen-api 兜底"的双引擎结构——这也解释了为什么 Props 表格对 events、slots 的支持在当前版本中比文档写作时期更完善。
四、DocsPage:零配置的自动文档
安装完 Docs 后,每个 Story 都会自动获得 DocsPage:它从 Story 元数据、组件 docgen 信息、源代码描述等多处收集内容,拼装成一个可读的文档页,出现在 Storybook UI 的Docs标签。
要让 DocsPage 准确关联到你的组件,关键是在 Story 的默认导出(meta)中填写component字段:
import { InfoButton } from './InfoButton.vue'; export default { title: 'InfoButton', component: InfoButton, };component字段是 Docs 将"Story"与"组件类型信息"关联起来的锚点:没有它,DocsPage 仍能渲染 Story,但 Props 表格、Args 分类等依赖 docgen 的部分将无从匹配。
五、Props 表格
Props 表格(参考文档)是 Vue 3 Docs 的核心能力之一。对 Vue,它依赖上文提到的 docgen 提取链路,并对三种 Vue 一等公民属性提供了原生支持:
- props:组件的 props 声明(
defineProps/ Options APIprops); - events:组件事件(
defineEmits/ Options APIemits); - slots:模板插槽(
<slot>声明及 slot props)。
生成 Props 表格的前提条件:
- 已安装并注册
@storybook/addon-docs; - 项目路径别名等已按需通过
vueDocgenOptions.alias配置(见第三节); - Story meta 中填写了
component字段(见第四节示例)。
满足后,<ArgsTable>或 DocsPage 的 Props 区块即会自动列出组件的 props / events / slots 及其类型。
六、MDX:长文文档
MDX 适合撰写长篇组件文档:用 Markdown 行文,并在文中直接嵌入 Story、ArgsTable 等文档组件。
前置依赖与配置
Docs 对react存在 peer dependency(MDX 编译工具链需要)。如果你要写 MDX 文档,可能需要显式补装:
yarn add -D react然后更新.storybook/main.js,让 stories glob 匹配.mdx文件:
export default { stories: ['../src/stories/**/*.stories.@(js|mdx)'], };MDX 文件示例
下面是一个 Vue 3 组件的完整 MDX 示例(继承自官方文档原文,可复制后按你的组件名修改):
import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; import { InfoButton } from './InfoButton.vue'; <Meta title='InfoButton' component={InfoButton} /> # InfoButton Some **markdown** description, or whatever you want. <Story name='basic' height='400px'>{{ components: { InfoButton }, template: '<info-button label="I\'m a button!"/>', }}</Story> ## ArgsTable <ArgsTable of={InfoButton} />示例要点:
<Meta component={InfoButton} />将 MDX 页与组件绑定,使 ArgsTable 和 docgen 信息生效;<Story>内联传入了一个 Options API 风格的渲染对象(components+template),在 MDX 中直接渲染任意模板;<ArgsTable of={InfoButton} />渲染该组件的 Args 表格。
原文档还特别注明:component在<Meta>与 story 中重复声明是当时(5.x 时期)的冗余设计。如果你在使用老版本的示例代码遇到"component 声明两次"的困惑,这正是原因。
七、Inline Stories:内联渲染与 iframe 高度
Storybook Docs 默认以**内联(inline)**方式渲染所有 Vue Story。如果需要将 Story 渲染在 iframe 中(例如隔离全局样式),可以使用docs.stories.inline参数;iframe 模式下的默认高度可配置,原文档标注为 60px,配置键为docs.story.iframeHeight。
对全部 Story 生效时,修改.storybook/preview.js:
export const parameters = { docs: { story: { inline: false } } };该参数同样可以下沉到单个 Story 或 meta 级别。从当前源码看,高度的取值优先级与回退值定义在 code/addons/docs/src/blocks/blocks/Story.tsx:
const storyParameters = (docs.story || {}) as StoryParameters & { iframeHeight?: string }; // ... const height = props.height ?? storyParameters.height ?? storyParameters.iframeHeight ?? '100px';即<Story height="...">组件属性优先,其次是docs.story.height,再次是docs.story.iframeHeight,都没有时回退到'100px'——可见当前版本对 iframe 高度的兜底值已从文档早期标注的 60px 演进为 100px,iframeHeight作为旧配置键仍被兼容读取。参数类型定义可参考 code/addons/docs/src/types.ts。
八、延伸阅读
围绕 Storybook Docs 的完整参考文档(均位于本仓库内):
- DocsPage:DocsPage 的组成与工作机制;
- MDX:MDX 块组件全集(
<Meta>/<Canvas>/<Story>/<ArgsTable>等); - Props 表格:props 表与 TypeScript 配置;
- FAQ、Recipes、Theming。
Vue 3 渲染器侧的配套实现与测试可作为深入阅读入口:Vue3 渲染器源码、docgen 工作进程、以及沙箱中的示例组件 code/renderers/vue3/template/stories_vue3-vite-default-ts,其中包含ReactiveArgs、ScopedSlots、GlobalSetup等典型 Vue 3 特性 Story,可作为 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),仅供参考