Docs
Storybook Docs

参数

Watch a video tutorial

故事是一个组件,带有一组参数,这些参数定义组件应如何渲染。“Args”是 Storybook 在单个 JavaScript 对象中定义这些参数的机制。Args 可用于动态更改属性、插槽、样式、输入等。它允许 Storybook 及其插件实时编辑组件。你不需要修改底层组件代码来使用 args。

¥A story is a component with a set of arguments that define how the component should render. “Args” are Storybook’s mechanism for defining those arguments in a single JavaScript object. Args can be used to dynamically change props, slots, styles, inputs, etc. It allows Storybook and its addons to live edit components. You do not need to modify your underlying component code to use args.

当 arg 的值发生变化时,组件会重新渲染,允许你通过影响 args 的插件与 Storybook 的 UI 中的组件进行交互。

¥When an arg’s value changes, the component re-renders, allowing you to interact with components in Storybook’s UI via addons that affect args.

了解如何以及为什么在 简介 中编写故事。有关 args 如何工作的详细信息,请继续阅读。

¥Learn how and why to write stories in the introduction. For details on how args work, read on.

参数对象

¥Args object

args 对象可以在 storycomponent全局级别 中定义。它是一个 JSON 可序列化对象,由具有匹配有效值类型的字符串键组成,可以传递到框架的组件中。

¥The args object can be defined at the story, component and global level. It is a JSON serializable object composed of string keys with matching valid value types that can be passed into a component for your framework.

故事参数

¥Story args

要定义单个故事的参数,请使用 args CSF 故事键:

¥To define the args of a single story, use the args CSF story key:

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',
  },
};

这些参数仅适用于它们所附加的故事,尽管你可以通过 JavaScript 对象重用 reuse 它们:

¥These args will only apply to the story for which they are attached, although you can reuse them via JavaScript object reuse:

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 的 对象扩展 功能。

¥In the above example, we use the object spread feature of ES 2015.

组件参数

¥Component args

你还可以在组件级别定义参数;除非你覆盖它们,否则它们将应用于所有组件的故事。为此,请在 default CSF 导出上使用 args 键:

¥You can also define args at the component level; they will apply to all the component's stories unless you overwrite them. To do so, use the args key on the default CSF export:

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>;

全局参数

¥Global args

你还可以在全局级别定义参数;除非你覆盖它们,否则它们将应用于每个组件的故事。为此,请在 preview.js 的默认导出中定义 args 属性:

¥You can also define args at the global level; they will apply to every component's stories unless you overwrite them. To do so, define the args property in the default export of preview.js:

.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;

对于大多数全局参数的使用,globals 是定义全局应用设置(例如主题)的更好工具。使用全局变量使用户能够使用工具栏菜单更改值。

¥For most uses of global args, globals are a better tool for defining globally-applied settings, such as a theme. Using globals enables users to change the value with the toolbar menu.

参数组成

¥Args composition

你可以将故事的参数分开,以便在其他故事中编写。以下是如何组合同一组件的多个故事的参数。

¥You can separate the arguments to a story to compose in other stories. Here's how you can combine args for multiple stories of the same component.

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,
  },
};

如果你发现自己对大多数组件的故事重复使用相同的参数,则应考虑使用 组件级参数

¥If you find yourself re-using the same args for most of a component's stories, you should consider using component-level args.

在为由其他组件组装而成的复合组件编写故事时,参数很有用。复合组件通常将其参数不加改变地传递给其子组件,同样,它们的故事可以是其子组件故事的组合。使用 args,你可以直接编写参数:

¥Args are useful when writing stories for composite components that are assembled from other components. Composite components often pass their arguments unchanged to their child components, and similarly, their stories can be compositions of their child components stories. With args, you can directly compose the arguments:

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 can modify any aspect of your component

你可以在故事中使用参数来配置组件的外观,类似于你在应用中所做的操作。例如,以下是你可以使用 footer 参数填充子组件的方法:

¥You can use args in your stories to configure the component's appearance, similar to what you would do in an application. For example, here's how you could use a footer arg to populate a child component:

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 设置参数

¥Setting args through the URL

你还可以通过向 URL 添加 args 查询参数来覆盖活动故事的初始参数集。通常你会使用 控件插件 来处理这个问题。例如,以下是你可以在 Storybook 的 URL 中设置 sizestyle 参数的方法:

¥You can also override the set of initial args for the active story by adding an args query parameter to the URL. Typically you would use the Controls addon to handle this. For example, here's how you could set a size and style arg in the Storybook's URL:

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

作为针对 XSS 攻击的保障措施,URL 中提供的 arg 的键和值仅限于字母数字字符、空格、下划线和破折号。任何其他类型都将被忽略并从 URL 中删除,但你仍然可以将它们与控件插件和 在你的故事中 一起使用。

¥As a safeguard against XSS attacks, the arg's keys and values provided in the URL are limited to alphanumeric characters, spaces, underscores, and dashes. Any other types will be ignored and removed from the URL, but you can still use them with the Controls addon and within your story.

args 参数始终是一组用分号 ; 分隔的 key: value 对。值将被强制(转换)为各自的 argTypes(可能已自动推断)。支持对象和数组。特殊值 nullundefined 可以通过在前缀中添加感叹号 ! 来设置。例如,args=obj.key:val;arr[0]:one;arr[1]:two;nil:!null 将被解释为:

¥The args param is always a set of key: value pairs delimited with a semicolon ;. Values will be coerced (cast) to their respective argTypes (which may have been automatically inferred). Objects and arrays are supported. Special values null and undefined can be set by prefixing with a bang !. For example, args=obj.key:val;arr[0]:one;arr[1]:two;nil:!null will be interpreted as:

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

同样,日期和颜色也有特殊格式。日期对象将被编码为 !date(value),其值表示为 ISO 日期字符串。颜色编码为 !hex(value)!rgba(value)!hsla(value)。请注意,rgb(a) 和 hsl(a) 不应在 URL 中包含空格或百分号。

¥Similarly, special formats are available for dates and colors. Date objects will be encoded as !date(value) with value represented as an ISO date string. Colors are encoded as !hex(value), !rgba(value) or !hsla(value). Note that rgb(a) and hsl(a) should not contain spaces or percentage signs in the URL.

通过 URL 指定的 Args 将扩展并覆盖故事中设置的任何默认值。

¥Args specified through the URL will extend and override any default values of args set on the story.

在故事中设置参数

¥Setting args from within a story

交互式组件通常需要由其包含的组件或页面控制,以响应事件、修改其状态并在 UI 中反映这些更改。例如,当用户切换开关组件时,应检查开关,并且 Storybook 中显示的参数应反映更改。要启用此功能,你可以使用 @storybook/preview-api 导出的 useArgs API:

¥Interactive components often need to be controlled by their containing component or page to respond to events, modify their state and reflect those changes in the UI. For example, when a user toggles a switch component, the switch should be checked, and the arg shown in Storybook should reflect the change. To enable this, you can use the useArgs API exported by @storybook/preview-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} />;
  },
};

映射到复杂参数值

¥Mapping to complex arg values

复杂值(例如 JSX 元素)无法序列化到管理器(例如,控件插件)或与 URL 同步。可以使用 argTypes 中的 mapping 属性将 Arg 值从简单字符串转换为复杂类型,以解决此限制。它在任何参数中都有效,但与 select 控件类型一起使用时最有意义。

¥Complex values such as JSX elements cannot be serialized to the manager (e.g., the Controls addon) or synced with the URL. Arg values can be "mapped" from a simple string to a complex type using the mapping property in argTypes to work around this limitation. It works in any arg but makes the most sense when used with the select control type.

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 中的键始终对应于 arg 值,而不是它们在 options 数组中的索引。

¥Note that mapping does not have to be exhaustive. If the arg value is not a property of mapping, the value will be used directly. Keys in mapping always correspond to arg values, not their index in the options array.

Using args in addons

如果你是想要读取或更新参数的 编写插件,请使用 @storybook/manager-api 导出的 useArgs 钩子:

¥If you are writing an addon that wants to read or update args, use the useArgs hook exported by @storybook/manager-api:

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();