在 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") },
});