参加直播:美国东部时间周四上午 11 点,Storybook 9 发布 & AMA
文档
Storybook Docs

适用于 Vue & Vite 的 Storybook

适用于 Vue & Vite 的 Storybook 是一个框架,使得独立开发和测试用于使用 Vite 构建的 Vue 应用的 UI 组件变得容易。它包括:

  • 🏎️ 为性能预先打包
  • 🪄 零配置
  • 🧠 全面的文档生成
  • 💫 等等!

要求

  • Vue ≥ 3
  • Vite ≥ 5.0

入门

在没有 Storybook 的项目中

在你的 Vue 项目根目录中运行此命令后,按照提示操作

npm create storybook@latest

更多关于 Storybook 入门的信息。

在已有 Storybook 的项目中

此框架旨在与 Storybook 7+ 一起使用。如果你尚未升级到 v7,请使用此命令升级

npx storybook@next upgrade

自动迁移

运行上面的 upgrade 命令时,你应该会收到提示,要求你迁移到 @storybook/vue3-vite,这应该会自动处理所有事情。如果自动迁移不适用于你的项目,请参考下面的手动迁移。

手动迁移

首先,安装框架

npm install --save-dev @storybook/vue3-vite

然后,更新你的 .storybook/main.js|ts 文件以更改 framework 属性

.storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';
 
const config: StorybookConfig = {
  // ...
  framework: '@storybook/vue3-vite', // 👈 Add this
};
 
export default config;

扩展 Vue 应用

Storybook 会为你的组件预览创建一个Vue 3 应用。当使用全局自定义组件(app.component)、指令(app.directive)、扩展(app.use)或其他应用方法时,你需要配置它们在 ./storybook/preview.js|ts 文件中。

因此,Storybook 提供了一个从这个包中导出的 setup 函数。这个函数接收你的 Storybook 实例作为回调,你可以与其交互并添加你的自定义配置。

.storybook/preview.js|ts
import { setup } from '@storybook/vue3-vite';
 
setup((app) => {
  app.use(MyPlugin);
  app.component('my-component', MyComponent);
  app.mixin({
    // My mixin
  });
});

使用 vue-component-meta

vue-component-meta 仅在 Storybook ≥ 8 中可用。它目前是可选启用的,但将在未来版本的 Storybook 中成为默认设置。

vue-component-meta 是由 Vue 团队维护的一个工具,用于从 Vue 组件中提取元数据。Storybook 可以使用它来为你的故事和文档生成控制项。它是 vue-docgen-api 更具完整功能的替代品,推荐用于大多数项目。

如果你想使用 vue-component-meta,你可以在你的 .storybook/main.js|ts 文件中配置它

.storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';
 
const config: StorybookConfig = {
  framework: {
    name: '@storybook/vue3-vite',
    options: {
      docgen: 'vue-component-meta',
    },
  },
};
 
export default config;

vue-component-meta 带来许多好处,并支持更多的文档功能,例如

支持多种组件类型

vue-component-meta 支持所有类型的 Vue 组件(包括 SFC、函数式组件、组合式/选项式 API 组件),支持 .vue.ts.tsx.js.jsx 文件。

它还支持默认导出和命名导出组件。

Prop 描述和 JSDoc 标签注解

要描述一个 prop,包括标签,你可以在组件的 props 定义中使用 JSDoc 注释

YourComponent.vue
<script setup lang="ts">
  interface MyComponentProps {
    /** The name of the user */
    name: string;
    /**
      * The category of the component
      *
      * @since 8.0.0
      */
    category?: string;
  }
 
  withDefaults(defineProps<MyComponentProps>(), {
    category: 'Uncategorized',
  });
</script>

上面的 props 定义将生成以下控制项

Controls generated from props

事件类型提取

要为发出的事件提供类型,你可以在组件的 defineEmits 调用中使用 TypeScript 类型(包括 JSDoc 注释)

YourComponent.vue
<script setup lang="ts">
  type MyChangeEvent = 'change';
 
  interface MyEvents {
    /** Fired when item is changed */
    (event: MyChangeEvent, item?: Item): void;
    /** Fired when item is deleted */
    (event: 'delete', id: string): void;
    /** Fired when item is upserted into list */
    (e: 'upsert', id: string): void;
  }
 
  const emit = defineEmits<MyEvents>();
</script>

这将生成以下控制项

Controls generated from events

插槽类型提取

插槽类型会自动从你的组件定义中提取,并在控制面板中显示。

YourComponent.vue
<template>
  <slot :num="123"></slot>
  <br />
  <slot name="named" str="str"></slot>
  <br />
  <slot name="no-bind"></slot>
  <br />
  <slot name="vbind" v-bind="{ num: 123, str: 'str' }"></slot>
</template>
 
<script setup lang="ts"></script>

如果你使用 defineSlots,你可以在组件的插槽定义中使用 JSDoc 注释描述每个插槽

defineSlots<{
  /** Example description for default */
  default(props: { num: number }): any;
  /** Example description for named */
  named(props: { str: string }): any;
  /** Example description for no-bind */
  noBind(props: {}): any;
  /** Example description for vbind */
  vbind(props: { num: number; str: string }): any;
}>();

上面的定义将生成以下控制项

Controls generated from slots

暴露的属性和方法

组件暴露的属性和方法会自动提取,并在控制面板中显示。

YourComponent.vue
<script setup lang="ts">
  import { ref } from 'vue';
 
  const label = ref('Button');
  const count = ref(100);
 
  defineExpose({
    /** A label string */
    label,
    /** A count number */
    count,
  });
</script>

上面的定义将生成以下控制项

Controls generated from exposed properties and methods

覆盖默认配置

如果你正在处理依赖 tsconfig 引用 来链接到其他现有配置文件(例如 tsconfig.app.jsontsconfig.node.json)的项目,我们建议你更新你的.storybook/main.js|ts 配置文件并添加以下内容

.storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';
 
const config: StorybookConfig = {
  framework: {
    name: '@storybook/vue3-vite',
    options: {
      docgen: {
        plugin: 'vue-component-meta',
        tsconfig: 'tsconfig.app.json',
      },
    },
  },
};
 
export default config;

这不是 Storybook 的限制,而是 vue-component-meta 的工作方式。欲了解更多信息,请参考相关的GitHub Issue

否则,你可能会遇到组件类型/描述缺失或无法解析的导入别名,例如 @/some/import

故障排除

Storybook 不支持我的 Vue 2 项目

Vue 2 于 2023 年 12 月 31 日到达终止生命周期 (EOL),不再由 Vue 团队维护。因此,Storybook 不再支持 Vue 2。我们建议你将项目升级到 Storybook 完全支持的 Vue 3。如果这不是一个选项,你仍然可以通过安装最新版本的 Storybook 7 来使用 Vue 2,命令如下

npx storybook@^7 init

API

选项

你可以传递一个选项对象以进行额外的配置(如果需要)

.storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';
 
const config: StorybookConfig = {
  framework: {
    name: '@storybook/vue3-vite',
    options: {
      docgen: 'vue-component-meta',
    },
  },
};
 
export default config;

builder

类型:Record<string, any>

配置框架构建器的选项。对于此框架,可用选项可以在Vite 构建器文档中找到。

docgen

类型:'vue-docgen-api' | 'vue-component-meta'

默认值:'vue-docgen-api'

自版本:8.0

选择为你的组件生成控制项时使用的 docgen 工具。更多信息请参见使用 vue-component-meta