文件
Storybook 文件

Args

觀看影片教學

故事是一個元件,具有一組定義元件應如何渲染的引數。「Args」是 Storybook 用於在單一 JavaScript 物件中定義這些引數的機制。Args 可用於動態變更 props、slots、樣式、輸入等。它允許 Storybook 及其附加元件即時編輯元件。您需要修改底層元件程式碼即可使用 args。

當 arg 的值變更時,元件會重新渲染,讓您可以透過影響 args 的附加元件,在 Storybook 的 UI 中與元件互動。

了解如何以及為何在簡介中撰寫故事。如需 args 如何運作的詳細資訊,請繼續閱讀。

Args 物件

args 物件可以在故事元件全域層級定義。它是一個 JSON 可序列化的物件,由字串索引鍵組成,這些索引鍵具有相符的有效值類型,可以傳遞至您框架的元件。

故事 args

若要定義單一故事的 args,請使用 args CSF 故事索引鍵

Button.stories.ts|tsx
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 將僅適用於它們附加到的故事,但您可以透過 JavaScript 物件重複使用來重複使用它們

Button.stories.ts|tsx
// 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;它們將適用於元件的所有故事,除非您覆寫它們。若要執行此操作,請在 default CSF 匯出上使用 args 索引鍵

Button.stories.ts|tsx
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;它們將適用於每個元件的故事,除非您覆寫它們。若要執行此操作,請在 preview.js 的預設匯出中定義 args 屬性

.storybook/preview.ts
// 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 組件

您可以將故事的引數分開,以在其他故事中組成。以下是如何組合相同元件的多個故事的 args。

Button.stories.ts|tsx
// 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,
  },
};

如果您發現自己為元件的大部分故事重複使用相同的 args,則應考慮使用元件層級 args

當為由其他元件組成的複合元件撰寫故事時,Args 非常有用。複合元件通常會將其引數原封不動地傳遞給其子元件,類似地,它們的故事也可以是其子元件故事的組合。透過 args,您可以直接組合引數

Page.stories.ts|tsx
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 可以修改元件的任何層面

您可以在故事中使用 args 來設定元件的外觀,類似於在應用程式中會執行的操作。例如,以下說明如何使用 footer arg 來填入子元件

Page.stories.ts|tsx
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您也可以透過在 URL 中加入 args 查詢參數來覆寫目前 Story 的初始參數設定。一般來說,您會使用 Controls 附加元件來處理這個問題。例如,以下是如何在 Storybook 的 URL 中設定 sizestyle 參數的方法

?path=/story/avatar--default&args=style:rounded;size:100

為了防範 XSS 攻擊,URL 中提供的參數鍵和值僅限於字母數字字元、空格、底線和破折號。任何其他類型都會被忽略並從 URL 中移除,但您仍然可以使用 Controls 附加元件以及在您的 Story 中使用它們。

args 參數始終是一組以分號 ; 分隔的 key: value 配對。值將會被強制轉換(cast)為它們各自的 argTypes(可能已經自動推斷出來)。物件和陣列都支援。特殊值 nullundefined 可以透過加上驚嘆號 ! 作為前綴來設定。例如,args=obj.key:val;arr[0]:one;arr[1]:two;nil:!null 將會被解讀為

{
  obj: { key: 'val' },
  arr: ['one', 'two'],
  nil: null
}

同樣地,特殊格式可用於日期和顏色。日期物件將會編碼為 !date(value),其中 value 表示為 ISO 日期字串。顏色將會編碼為 !hex(value)!rgba(value)!hsla(value)。請注意,rgb(a) 和 hsl(a) 在 URL 中不應包含空格或百分比符號。

透過 URL 指定的參數將會擴展並覆寫在 Story 中設定的任何參數預設值。

從 Story 內部設定參數

互動式元件通常需要由其包含的元件或頁面控制,以回應事件、修改其狀態並在 UI 中反映這些變更。例如,當使用者切換開關元件時,該開關應被勾選,並且 Storybook 中顯示的參數應反映此變更。若要啟用此功能,您可以使用 @storybook/preview-api 匯出的 useArgs API。

my-component/component.stories.ts|tsx
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} />;
  },
};

對應至複雜參數值

諸如 JSX 元素之類的複雜值無法序列化到管理器(例如 Controls 附加元件)或與 URL 同步。可以使用 argTypes 中的 mapping 屬性,將參數值從簡單的字串「對應」到複雜的類型,以解決此限制。它可以在任何參數中使用,但在與 select 控制類型一起使用時最有意義。

Example.stories.ts|tsx
// 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 不必是詳盡無遺的。如果參數值不是 mapping 的屬性,則會直接使用該值。mapping 中的鍵始終對應於參數,而不是它們在 options 陣列中的索引。

在附加元件中使用參數

如果您正在撰寫想要讀取或更新參數的附加元件,請使用 @storybook/manager-api 匯出的 useArgs Hook。

my-addon/src/manager.js|ts
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();