Stories

Detail Return Return

前端藝術實踐:用Storybook構建交互式組件文檔 - Stories Detail

對於前端來説,組件話已經從熱門話題變成了基礎能力,自定義組件或自建組件庫已是再常見不過的事了。在實際工作中組件庫的文檔直接決定開發體驗和效率,文檔建設的重要性不言而喻。今天要推薦的工具叫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 面板上實時展示事件調用及參數,對於組件自測非常友好,能夠幫助開發者快速驗證組件的交互行為。


秀一波文檔效果:

效果預覽完整Demo

image


添加交互邏輯:讓組件動起來


為了讓文檔更生動直觀,我們會添加一些帶交互或狀態的組件示例。由於在 Storybook 中的寫法幾乎和正常開發一樣,我們需要將文件後綴改為 .tsx,以支持 JSX 和類型。先上示例代碼,這是Demo中 Dropdown 組件搜索功能的文檔代碼片段:

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

image


豐富文檔內容:自動生成 vs 手動編輯


Storybook中, 有兩種方式可以為文檔添加豐富的圖文介紹:

  • 使用Autodocs自動生成的基礎模板,通過Meta配置的parameters.docs屬性,為組件添加介紹內容;
  • 使用MDX為每個組件創建自定義的文檔頁面。

Autodocs

Autodocs 是 Storybook 的一個功能,它通過讀取Metaparameters.docs屬性內容自動生成組件文檔。Autodocs 生成的文檔會優先展示第一個示例(Primary)的內容以及組件的Props列表,然後再依次展示所有的Story。

Autodocs 的使用方式非常簡單,如同上面的案例一樣,只需在export default的內容中添加 tags: ['autodocs'],即可( 跳轉至Hello World查看代碼 )。


MDX

MDX 是 Storybook 提供的一項強大功能,它允許我們在文檔中同時使用 Markdown 和 JSX(Vue 用户也可以使用相應語法),從而打造更靈活、更可控的組件文檔體驗。藉助 MDX,我們不僅可以像寫博客一樣撰寫説明文字,還可以在任意位置嵌入組件實例、添加交互示例、引入自定義樣式和佈局,甚至封裝文檔模板來複用常見結構。

相比於 Storybook 的 Autodocs(自動生成的參數+交互頁面),MDX 提供了完全的內容主導權,我們可以自由決定文檔的結構、順序與樣式:比如先講背景、再展示組件、最後講參數,或者將多個組件組合成場景化示例頁,而不受自動文檔生成邏輯的限制。

這種方式特別適合需要講解上下文、構建複雜交互示例,或者進行教學類文檔的場景。它讓組件文檔不僅“可用”,還“可講、可演示”,真正實現文檔與設計、開發的融合。


最後


組件文檔不是附加項,而是組件庫的標配。Storybook 不僅能寫文檔,還支持組件自動化測試,真的是又能打又好用。如果你還沒試過,強烈建議親自體驗一下!

我已將部分 Storybook 相關文檔整理髮布在個人網站(aser1989.cn)上,歡迎查閲。

感謝閲讀,覺得不錯的話,歡迎點贊支持~✌️

user avatar cyzf Avatar Leesz Avatar alibabawenyujishu Avatar haoqidewukong Avatar nihaojob Avatar kobe_fans_zxc Avatar aqiongbei Avatar chongdianqishi Avatar razyliang Avatar longlong688 Avatar huajianketang Avatar xiaoxxuejishu Avatar
Favorites 65 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.