Decorators
觀看影片教學
Decorator 是一種將 story 包裹在額外「渲染」功能中的方式。許多附加元件定義了 decorator,以使用額外渲染來擴增您的 stories,或收集有關您的 story 如何渲染的詳細資訊。
在撰寫 stories 時,decorators 通常用於使用額外的標記或情境模擬來包裹 stories。
使用額外的標記包裹 stories
某些元件需要「外框」才能以有用的方式渲染。例如,如果元件一直延伸到其邊緣,您可能會希望在 Storybook 內部間隔它。使用 decorator 為元件的所有 stories 新增間隔。
import type { Meta } from '@storybook/react';
import { YourComponent } from './YourComponent';
const meta: Meta<typeof YourComponent> = {
component: YourComponent,
decorators: [
(Story) => (
<div style={{ margin: '3em' }}>
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
<Story />
</div>
),
],
};
export default meta;
「情境」用於模擬
decorator 函數的第二個引數是 story 情境,其中包含下列屬性
args
- story 引數。您可以在 decorator 中使用一些args
,並將它們放入 story 實作本身中。argTypes
- Storybook 的 argTypes 可讓您自訂和微調 storiesargs
。globals
- Storybook 範圍的 全域變數。特別是,您可以使用工具列功能,讓您使用 Storybook 的 UI 變更這些值。hooks
- Storybook 的 API hooks (例如,useArgs)。parameters
- story 的靜態中繼資料,最常用於控制 Storybook 的功能和附加元件的行為。viewMode
- Storybook 目前的活動視窗 (例如,畫布、文件)。
此情境可用於根據 story 的引數或其他中繼資料調整 decorator 的行為。例如,您可以建立一個 decorator,讓您透過定義 parameters.pageLayout = 'page'
(或 'page-mobile'
) 來選擇性地將版面配置套用至 story:
import React from 'react';
import type { Preview } from '@storybook/react';
const preview: Preview = {
decorators: [
// 👇 Defining the decorator in the preview file applies it to all stories
(Story, { parameters }) => {
// 👇 Make it configurable by reading from parameters
const { pageLayout } = parameters;
switch (pageLayout) {
case 'page':
return (
// Your page layout is probably a little more complex than this ;)
<div className="page-layout">
<Story />
</div>
);
case 'page-mobile':
return (
<div className="page-mobile-layout">
<Story />
</div>
);
default:
// In the default case, don't apply a layout
return <Story />;
}
},
],
};
export default preview;
如需另一個範例,請參閱關於設定模擬提供者的章節,其中示範如何使用相同的技術來變更提供給元件的主題。
使用 decorators 提供資料
如果您的元件是「已連線」且需要側載資料才能渲染,您可以使用 decorators 以模擬方式提供該資料,而無需重構您的元件以將該資料作為引數。有幾種技術可以實現此目的。取決於您載入資料的確切方式。請在在 Storybook 中建立頁面章節中閱讀更多資訊。
Story decorators
若要為單一 story 定義 decorator,請在具名匯出上使用 decorators
鍵
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
decorators: [
(Story) => (
<div style={{ margin: '3em' }}>
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
<Story />
</div>
),
],
};
確保 story 仍然是受測元件的「純粹」渲染,並且任何額外的 HTML 或元件僅用作 decorators,這會很有用。特別是,當您執行此操作時,Source 文件區塊效果最佳。
元件 decorators
若要為元件的所有 stories 定義 decorator,請使用預設 CSF 匯出的 decorators
鍵
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
decorators: [
(Story) => (
<div style={{ margin: '3em' }}>
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
<Story />
</div>
),
],
};
export default meta;
全域 decorators
我們也可以透過您的 .storybook/preview.js|ts
檔案 (這是您設定所有 stories 的檔案) 的 decorators
匯出,為所有 stories 設定 decorator
import React from 'react';
import { Preview } from '@storybook/react';
const preview: Preview = {
decorators: [
(Story) => (
<div style={{ margin: '3em' }}>
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
<Story />
</div>
),
],
};
export default preview;
Decorator 繼承
與參數類似,decorators 可以全域定義、在元件層級定義,以及針對單一 story 定義 (如我們所見)。
一旦 story 渲染,所有與 story 相關的 decorators 將依下列順序執行
- 全域 decorators,依定義順序
- 元件 decorators,依定義順序
- Story decorators,依定義順序,從最內層的 decorator 開始,向外並向上階層以相同順序運作