Args
觀看影片教學
一個 story 是一個元件,帶有一組定義元件應如何渲染的參數。「Args」是 Storybook 用於在單一 JavaScript 物件中定義這些參數的機制。Args 可以用來動態變更 props、slots、styles、inputs 等。它允許 Storybook 及其附加元件即時編輯元件。您不需要修改底層元件程式碼即可使用 args。
當 arg 的值變更時,元件會重新渲染,讓您透過影響 args 的附加元件,在 Storybook 的 UI 中與元件互動。
了解如何在簡介中編寫 stories 以及為何要這樣做。如需 args 如何運作的詳細資訊,請繼續閱讀。
Args 物件
args
物件可以在story、元件和全域層級定義。它是一個 JSON 可序列化物件,由字串鍵和相符的有效值類型組成,可以傳遞到您框架的元件中。
Story args
若要定義單一 story 的 args,請使用 args
CSF story 鍵
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 = {
args: {
primary: true,
label: 'Button',
},
};
這些 args 只會套用至它們所附加的 story,但您可以透過 JavaScript 物件重複使用來重複使用它們
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};
export const PrimaryLongName: Story = {
args: {
...Primary.args,
label: 'Primary with a really long name',
},
};
在以上範例中,我們使用了 ES 2015 的物件展開功能。
元件 args
您也可以在元件層級定義 args;它們將套用至元件的所有 stories,除非您覆寫它們。若要這麼做,請在 default
CSF 匯出上使用 args
鍵
import type { Meta } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
//👇 Creates specific argTypes
argTypes: {
backgroundColor: { control: 'color' },
},
args: {
//👇 Now all Button stories will be primary.
primary: true,
},
};
export default meta;
type Story = StoryObj<typeof Button>;
全域 args
您也可以在全域層級定義 args;它們將套用至每個元件的 stories,除非您覆寫它們。若要這麼做,請在 preview.js|ts
的預設匯出中定義 args
屬性
// Replace your-renderer with the renderer you are using (e.g., react, vue3, angular, etc.)
import { Preview } from '@storybook/your-renderer';
const preview: Preview = {
// The default value of the theme arg for all stories
args: { theme: 'light' },
};
export default preview;
對於全域 args 的大多數用途,全域變數是定義全域套用設定(例如主題)的更好工具。使用全域變數可讓使用者使用工具列選單變更值。
Args 組合
您可以分離 story 的參數,以在其他 stories 中組合。以下說明如何組合相同元件的多個 stories 的 args。
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};
export const Secondary: Story = {
args: {
...Primary.args,
primary: false,
},
};
如果您發現自己為元件的大多數 stories 重複使用相同的 args,則應考慮使用元件層級 args。
當為從其他元件組裝而成的複合元件編寫 stories 時,Args 非常有用。複合元件通常會將其參數不變地傳遞給其子元件,同樣地,它們的 stories 可以是其子元件 stories 的組合。透過 args,您可以直接組合參數
import type { Meta, StoryObj } from '@storybook/react';
import { Page } from './Page';
//👇 Imports all Header stories
import * as HeaderStories from './Header.stories';
const meta: Meta<typeof Page> = {
component: Page,
};
export default meta;
type Story = StoryObj<typeof Page>;
export const LoggedIn: Story = {
args: {
...HeaderStories.LoggedIn.args,
},
};
Args 可以修改元件的任何外觀
您可以在 stories 中使用 args 來設定元件的外觀,類似於您在應用程式中所做的事情。例如,以下說明如何使用 footer
arg 來填入子元件
import type { Meta, StoryObj } from '@storybook/react';
import { Page } from './Page';
type PagePropsAndCustomArgs = React.ComponentProps<typeof Page> & { footer?: string };
const meta: Meta<PagePropsAndCustomArgs> = {
component: Page,
render: ({ footer, ...args }) => (
<Page {...args}>
<footer>{footer}</footer>
</Page>
),
};
export default meta;
type Story = StoryObj<PagePropsAndCustomArgs>;
export const CustomFooter: Story = {
args: {
footer: 'Built with Storybook',
},
};
透過 URL 設定 args
您也可以透過將 args
查詢參數新增至 URL 來覆寫作用中 story 的初始 args 集。通常您會使用控制項附加元件來處理此問題。例如,以下說明如何在 Storybook 的 URL 中設定 size
和 style
arg
?path=/story/avatar--default&args=style:rounded;size:100
為了防範 XSS 攻擊,URL 中提供的 arg 的鍵和值僅限於英數字元、空格、底線和破折號。任何其他類型都會被忽略並從 URL 中移除,但您仍然可以使用控制項附加元件和 在您的 story 內使用它們。
args
參數始終是一組以分號 ;
分隔的 鍵: 值
配對。值將被強制轉換為其各自的 argTypes
(可能已自動推斷)。支援物件和陣列。特殊值 null
和 undefined
可以透過在前面加上驚嘆號 !
來設定。例如,args=obj.key:val;arr[0]:one;arr[1]:two;nil:!null
將被解讀為
{
obj: { key: 'val' },
arr: ['one', 'two'],
nil: null
}
同樣地,特殊格式也適用於日期和顏色。Date 物件將編碼為 !date(value)
,其中 value 表示為 ISO 日期字串。顏色編碼為 !hex(value)
、!rgba(value)
或 !hsla(value)
。請注意,rgb(a) 和 hsl(a) 不應在 URL 中包含空格或百分比符號。
透過 URL 指定的 Args 將擴展並覆寫在 story 上設定的任何 args 預設值。
從 story 內設定 args
互動式元件通常需要由其包含的元件或頁面控制,以回應事件、修改其狀態並在 UI 中反映這些變更。例如,當使用者切換開關元件時,應選取開關,且 Storybook 中顯示的 arg 應反映變更。若要啟用此功能,您可以使用 @storybook/preview-api
匯出的 useArgs
API
import { StoryObj, Meta } from '@storybook/react';
import { useArgs } from '@storybook/preview-api';
import { Checkbox } from './checkbox';
const meta: Meta<typeof Checkbox> = {
title: 'Inputs/Checkbox',
component: Checkbox,
};
export default meta;
type Story = StoryObj<typeof Checkbox>;
export const Example: Story = {
args: {
isChecked: false,
label: 'Try Me!',
},
/**
* 👇 To avoid linting issues, it is recommended to use a function with a capitalized name.
* If you are not concerned with linting, you may use an arrow function.
*/
render: function Render(args) {
const [{ isChecked }, updateArgs] = useArgs();
function onChange() {
updateArgs({ isChecked: !isChecked });
}
return <Checkbox {...args} onChange={onChange} isChecked={isChecked} />;
},
};
對應至複雜 arg 值
複雜值(例如 JSX 元素)無法序列化到管理器(例如,控制項附加元件)或與 URL 同步。可以使用 argTypes
中的 mapping
屬性,將 Arg 值從簡單字串「對應」到複雜類型,以解決此限制。它適用於任何 arg,但在與 select
控制項類型搭配使用時最合理。
// Replace your-renderer with the renderer you are using (e.g., react, vue3, angular, etc.)
import type { Meta } from '@storybook/your-renderer';
import { Example } from './Example';
const meta: Meta<typeof Example> = {
component: Example,
argTypes: {
label: {
options: ['Normal', 'Bold', 'Italic'],
mapping: {
Bold: <b>Bold</b>,
Italic: <i>Italic</i>,
},
},
},
};
export default meta;
請注意,mapping
不必詳盡無遺。如果 arg 值不是 mapping
的屬性,則將直接使用該值。mapping
中的鍵始終對應於 arg 值,而不是它們在 options
陣列中的索引。
在附加元件中使用 args
如果您正在編寫想要讀取或更新 args 的附加元件,請使用 @storybook/manager-api
匯出的 useArgs
Hook
import { useArgs } from '@storybook/manager-api';
const [args, updateArgs, resetArgs] = useArgs();
// To update one or more args:
updateArgs({ key: 'value' });
// To reset one (or more) args:
resetArgs((argNames: ['key']));
// To reset all args
resetArgs();