对于前端来说,组件话已经从热门话题变成了基础能力,自定义组件或自建组件库已是再常见不过的事了。在实际工作中组件库的文档直接决定开发体验和效率,文档建设的重要性不言而喻。今天要推荐的工具叫Storybook,为此我特地通过用99元买的服务器搭了一套CI/CD系统部署了一套Demo,欢迎点击体验:Demo (首次加载速度尤为感人,请耐心等待。仅用于效果演示,希望大家别被这潦草的Demo迷惑)。组件库的文档不只是“写说明”,更要做到可视化、可交互、可复用——既能看、又能点、还能直接抄代码。能够满足这些需求的文档工具中,重点推荐以下两款:DumiStorybook

Dumi


Dumi是一款为组件开发场景而生的静态站点框架,它有个代表作:Ant Design。不知是否有人跟我一样,第一眼看上的不是Ant Design的组件,而是它的组件库文档。真心嫉妒他们的这份文档,有案例、有代码、能交互,还有详细的参数说明。如果对它感兴趣可以点击Dumi传送门

Storybook


Storybook 是一个开源项目,在 GitHub 上已有 83K+ star。它不仅用于构建组件库文档,还能用于组件测试。推荐 Storybook 的主要原因如下:

  1. 可直接嵌入项目,在编写组件文档的同时进行组件编码和测试;
  2. 基于 TypeScript 组件类型定义自动生成组件参数文档;
  3. 允许在文档中动态修改组件参数值,实时预览不同效果
  4. 基础文档建设难度低(大多数 Demo 文档的编写时间不超过1分钟,主要得益于我的项目 Nebula Note,可实现快速内容替换)。
  5. 文档中可以使用第三方库来丰富文档效果,如:Swiper、Mermaid、MathJax 等等。
  6. 支持多种框架(React、Vue、Angular 等等),并且支持多种语言(TypeScript、JavaScript、HTML、CSS 等等)。

安装


1、在项目根目录下运行以下命令,Storybook 会自动检测你的框架(React、Vue、Angular 等)并进行相应的安装:

npx storybook@latest init

安装过程可能需要几分钟,完成后它会添加必要的Storybook依赖并生成 .storybook 配置目录然后在 src/stories/ 目录中创建示例组件。

运行


npm run storybook

默认情况下,Storybook 会在 http://localhost:6006/ 运行。虽然我们一行代码都没写,但已经可以看到Storybook提供的示例组件文档。

配置


在编写文档前,首先应该决定文档的存放方式:

  • 集中存放: 将所有文档统一放在指定目录,例如 src/stories/,类似于示例文档的管理方式。
  1. 优点:结构清晰,文档与业务代码解耦,方便统一管理。
  2. 适用场景:适合大规模组件库开发,尤其是需要独立维护文档的项目。
  • 跟随组件: 每个组件的 Story 文档与组件代码存放在一起,例如 src/components/Button/Button.stories.tsx。
  1. 优点:文档紧贴组件,便于开发和维护,不需要在多个目录之间跳转。
  2. 适用场景:适合产品型项目,组件文档随组件代码更新,保持同步。

如果选择跟随组件,则需要调整.storybook/main.js(或 main.ts),并指定文档路径,示例代码如下:


const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],

Hello World


先分享一个React版的示例。新建一个文档button.stories.ts, 内容如下:

import { Meta, StoryObj } from '@storybook/react';
import Button, { ButtonProps } from './index';
import { action } from '@storybook/addon-actions'; export default {
title: 'Atoms/Button', // 组件在 Storybook 中的分组与显示路径。`'Atoms/Button'` 表示组件会在 `Atoms` 分组下展示为 `Button`。
component: Button, // 关联的 React 组件
tags: ['autodocs'], // `'autodocs'` 表示启用自动文档生成功能
argTypes: {}, // 定义组件 props 的控制类型、分类、描述等
args: {}, // 为组件设置默认的 props 值,在所有 stories 中共享,可在 UI 面板中修改
} as Meta<ButtonProps>; export type Story = StoryObj<ButtonProps>;
export const Primary: Story = {
// 指定组件运行的props值,可在 UI 面板中修改
args: {
children: 'Button',
type: 'primary',
onClick: action('Button clicked'),
},
};

以上是一个完整的button文档代码。在 Storybook 的 stories 中,可以使用 actions 来监听按钮点击事件,action('Button clicked') 可以在 Action 面板上实时展示事件调用及参数,对于组件自测非常友好,能够帮助开发者快速验证组件的交互行为。



秀一波原创专属文档效果(不是图片,可点击体验):

.aser1989-demo-box { border: 1px solid rgba(239, 239, 239, 1); margin: 20px 5px; border-radius: 5px; overflow: hidden; box-shadow: 4px 3px 3px rgba(240, 240, 240, 1), 4px -3px 3px rgba(247, 247, 247, 1) }
.aser1989-demo-box .demo-box-header { padding: 10px 20px; border-bottom: 1px solid rgba(224, 224, 224, 1); font-size: 16px; color: rgba(0, 0, 0, 1); text-shadow: 1px 1px 1px rgba(224, 224, 224, 1); z-index: 1; position: relative; background: rgba(254, 254, 242, 1); display: flex; justify-content: space-between }
.aser1989-demo-box .demo-box-header .demo-box-title { transition: all 0.3s; height: 25px; cursor: default }
.aser1989-demo-box .demo-box-header .demo-box-title:hover { font-size: 17px }
.aser1989-demo-box .demo-box-header a { font-size: 16px; cursor: pointer }

效果预览完整Demo

添加交互逻辑:让组件动起来


为了让文档更生动直观,我们会添加一些带交互或状态的组件示例。由于在 Storybook 中的写法几乎和正常开发一样,我们需要将文件后缀改为 .tsx,以支持 JSX 和类型。先上示例代码,这是DemoDropdown 组件搜索功能的文档代码片段:

import React, { useEffect } from 'react';
import { useArgs } from '@storybook/preview-api';
// 此处省略了组件文档定义相关代码
......
export const Primary: Story = {
args: {
enableTags: [
{
tag: 'two',
color: '#ff0000',
},
{
tag: 'four',
color: 'orange',
},
],
options: [],
},
render: () => {
const options = [
{
value: '1',
label: 'Option one',
keyword: '1',
},
{
value: '2',
label: 'Option two',
keyword: '2',
},
{
value: '3',
label: 'Option three',
keyword: '3',
},
{
value: '4',
label: 'Option four',
keyword: '4',
},
];
const [args, updateArgs] = useArgs<DropdownProps<string>>();
useEffect(() => {
updateArgs({ options: options });
}, []);
const handleSearch = (keyword?: string) => {
if (keyword) {
const newOptions = options.filter((option) =>
option.label?.includes(keyword),
);
updateArgs({ options: newOptions });
} else {
updateArgs({ options: options });
}
}; return <Dropdown {...args} onSearch={handleSearch} />;
},
};

因为Dropdown是一个受控组件,所以这里使用了Storybook的useArgs 这个hooks,目的是为了把结果更新到参数面板上。从代码片段上可以看出,Storybook支持我们添加一个render函数来实现自定义的文档逻辑和效果,在render函数中我们可以正常使用React的功能。

效果预览完整Demo

丰富文档内容:自动生成 vs 手动编辑


Storybook中, 有两种方式可以为文档添加丰富的图文介绍:

  • 使用Autodocs自动生成的基础模板,通过Meta配置的parameters.docs属性,为组件添加介绍内容;
  • 使用MDX为每个组件创建自定义的文档页面。

Autodocs

Autodocs 是 Storybook 的一个功能,它通过读取Metaparameters.docs属性内容自动生成组件文档。Autodocs 生成的文档会优先展示第一个示例(Primary)的内容以及组件的Props列表,然后再依次展示所有的Story。如:

多个Story示例完整Demo

Autodocs 的使用方式非常简单,如同上面的案例一样,只需在export default的内容中添加 tags: ['autodocs'],即可( 跳转至Hello World查看代码 )。

MDX

MDX 是 Storybook 提供的一项强大功能,它允许我们在文档中同时使用 Markdown 和 JSX(Vue 用户也可以使用相应语法),从而打造更灵活、更可控的组件文档体验。借助 MDX,我们不仅可以像写博客一样撰写说明文字,还可以在任意位置嵌入组件实例、添加交互示例、引入自定义样式和布局,甚至封装文档模板来复用常见结构。

相比于 Storybook 的 Autodocs(自动生成的参数+交互页面),MDX 提供了完全的内容主导权,我们可以自由决定文档的结构、顺序与样式:比如先讲背景、再展示组件、最后讲参数,或者将多个组件组合成场景化示例页,而不受自动文档生成逻辑的限制。

这种方式特别适合需要讲解上下文、构建复杂交互示例,或者进行教学类文档的场景。它让组件文档不仅“可用”,还“可讲、可演示”,真正实现文档与设计、开发的融合。

最后


组件文档不是附加项,而是组件库的标配。Storybook 不仅能写文档,还支持组件自动化测试,真的是又能打又好用。如果你还没试过,强烈建议亲自体验一下!

我已将部分 Storybook 相关文档整理发布在个人网站(aser1989.cn)上,欢迎查阅。

感谢阅读,觉得不错的话,欢迎点赞支持~️

前端艺术实践:用Storybook构建交互式组件文档的更多相关文章

  1. 解析Markdown文件生成React组件文档

    前言 最近做的项目使用了微前端框架single-spa. 对于这类微前端框架而言,通常有个utility应用,也就是公共应用,里面是各个子应用之间可以共用的一些公共组件或者方法. 对于一个团队而言,项 ...

  2. Docz 用 MDX 写 React UI 组件文档

    Docz 用 MDX 写 React UI 组件文档 前言 为了提升开发效率,创建一套 UI 组件库是一种较为有效的方式之一:可以减少重复工作.提高可复用,所以现在越来越多团队开始创建自己的 UI 组 ...

  3. spring boot / cloud (三) 集成springfox-swagger2构建在线API文档

    spring boot / cloud (三) 集成springfox-swagger2构建在线API文档 前言 不能同步更新API文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...

  4. 解放生产力,自动化生成vue组件文档

    一.现状 Vue框架在前端开发中应用广泛,当一个多人开发的Vue项目经过长期维护之后往往会沉淀出很多的公共组件,这个时候经常会出现一个人 开发了一个组件而其他维护者或新接手的人却不知道这个组件是做什么 ...

  5. Spring Boot 入门系列(二十二)使用Swagger2构建 RESTful API文档

    前面介绍了如何Spring Boot 快速打造Restful API 接口,也介绍了如何优雅的实现 Api 版本控制,不清楚的可以看我之前的文章:https://www.cnblogs.com/zha ...

  6. 使用Swashbuckle构建RESTful风格文档

    本次和大家分享的是Swagger to WebApi的nuget包Swashbuckle:因为项目需要统一api文档的风格,并要支持多种开发语言(C#,java,python),所以首先想到的是swa ...

  7. springboot集成swagger2构建RESTful API文档

    在开发过程中,有时候我们需要不停的测试接口,自测,或者交由测试测试接口,我们需要构建一个文档,都是单独写,太麻烦了,现在使用springboot集成swagger2来构建RESTful API文档,可 ...

  8. Jenkins构建项目帮助文档

    Jenkins构建项目帮助文档 主要步骤 一.配置jdk 1.1.   下载jdk,安装到自己电脑磁盘的Java目录下(比如:D:\Java\jdk). 1.2.   Jdk环境变量的配置: 1. 鼠 ...

  9. 打造自己的Vue组件文档生成工具

    程序员最讨厌的两件事情,第一种是写文档,另一种是别人没有写文档.有没有直接根据vue组件生成文档的呢?当然是有的的.但第三方使用起来不一定能和现有项目结合使用,往往需要额外的注释用来标记提取信息.使用 ...

  10. springmvc+swagger构建Restful风格文档

    本次和大家分享的是java方面的springmvc来构建的webapi接口+swagger文档:上篇文章分享.net的webapi用swagger来构建文档,因为有朋友问了为啥.net有docpage ...

随机推荐

  1. 微软宣布更新SymCrypt加密库,新增对PQC算法的支持

    转载链接:https://mp.weixin.qq.com/s/aWXzPTWhxFpJVP1s0iwAtw 2024年9月9日,微软(Microsoft)在其博客中宣布,已开始在其开源核心加密库Sy ...

  2. Kotlin:闭包、lambda与匿名内部类

  3. IO流:File类的使用

     java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关 File 能新建.删除.重命名文件和目录,但 File 不能访问文件内容本身.如果需要访问文件内容本身,则需要使用输入/ ...

  4. VAE模型简析和精要(原理和代码)

    1. 前言 这篇博客主要用于记录VAE的原理部分. 一方面便于日后自己的温故学习,另一方面也便于大家的学习和交流. 如有不对之处,欢迎评论区指出错误,你我共同进步学习! 图均引用自4部分的博客!!!! ...

  5. ChatGpt怎么玩

    注册 梯子 先找好梯子, 归属地最好是米国之类的, 否则提示 OpenAI's services are not available in your country. 注: 最好用固定代理, 如tro ...

  6. 安全可信 | 通过双项测试!TeleDB实力亮剑!

    近日,天翼云TeleDB数据库在中国信通院"可信数据库"系列测试的赛道上,一次性跨越"分布式事务型数据库基础能力测试"与"性能测试"的双重大 ...

  7. Q:查看锁表进程,及杀死所有锁表进程sql

     查看锁表进程 SELECT DISTINCT decode(s.inst_id, 1, 'DB1', 2, 'DB2') 数据库服务器, decode(s.BLOCKING_SESSION, '', ...

  8. FreeSql学习笔记——4.联表

    前言   上一章节是查询,记录了简单的查询,比较看好的是分块.Dto映射和分页,除了简单的单表查询,更多的时候要用到联表查询,毕竟设计数据库是按照范式设计,FreeSql的联表操作有导航属性.Join ...

  9. Linux驱动---按键

    目录 一.Input子系统 1.1.简介 1.2.Input子系统构成 1.3.input_dev结构体 二.输入设备驱动开发流程 2.1.分配和初始化输入设备 2.2.注册设备 2.3.事件上报 2 ...

  10. openEuler 24.03 SP1下载clang-18的办法(RISC-V版)

      距离openEuler 24.03 SP1发版已经过去了一段时间了,值得注意的是,在这个新的发行版中,可以直接通过命令行下载clang18了!之前的发行版中clang的版本是17,可以直接dnf ...