Hey!
Billgo

EN

在 Vue 中使用 Storybook

2021 年 10 月 1 日

Storybook 是开发 UI 组件的优秀工具,不过把它和 Vue 搭配使用时,有一些细节需要注意。

下面是我在使用 Vue 构建一个小型组件库时遇到的问题,以及对应解决方案的整理。

注意:本文内容可能会随着时间变化而过时。写作时对应的是 2021 年 3 月 / Storybook 6.1。

生成文档

Storybook 内置的 Docs 插件可以根据组件代码和注释生成文档,但要记录 Vue 中的某些特性,比如插槽或事件,并不总是直观。底层上,Storybook 使用 vue-docgen-api 来解析组件。你可以查看它的 README,了解如何为 Storybook 标注组件。

通过 CSF 参数化 Vue 实例

Storybook 文档中没有明确说明的一点是:Component Story Format 中的额外属性会成为包含组件的 Vue 实例内部内容。这意味着你可以给组件的父级添加 data、methods、computed 等属性。这可以解决一些更复杂的 props 和交互问题。具体可参考下一节。

输入控件与 v-model

上面的方式可以让输入控件,以及使用 v-model 的组件按预期工作。

Storybook 的 controls 不会触发 v-model 所需的事件,而且被控制的值也无法由组件自身更新。因此,可以把值放到根实例的 data 中,并禁用它的 controls。

import MyInput from "../src/components/MyInput.vue";

export default {
  title: "Components/MyInput",
  component: MyInput,
  argTypes: {
    value: {
      table: { disable: true },
    },
  },
};

const Template = (args, { argTypes }) => ({
  props: Object.keys(argTypes).filter((x) => x !== "value"),
  data() {
    return { value: "" };
  },
  components: { MyInput },
  template: `<MyInput v-bind="$props" v-model="value" />`,
});

export const Primary = Template.bind({});

使用 Actions

Storybook 提供 Actions 来可视化组件事件,但 Vue 中使用 Actions 的方式还没有正式进入文档

import { action } from "@storybook/addon-actions";

import HelloWorld from "./hello-world";

export default {
  title: "Atoms / Hello World",
};

export const Default = () => ({
  components: { HelloWorld },
  template: '<hello-world @click="action"></hello-world>',
  methods: { action: action("clicked") },
});