Storybook 插件 Knobs
Storybook 插件 Knobs 允许您使用 Storybook UI 动态编辑属性。您还可以在 Storybook 的 stories 中将 Knobs 用作动态变量。
框架支持.
这就是 Knobs 的样子
查看上面的 Storybook 演示 或 观看此视频。
入门
首先,您需要将 Knobs 作为开发依赖项安装到您的项目中。
yarn add @storybook/addon-knobs --dev
在 .storybook/main.js
中
module.exports = {
addons: ['@storybook/addon-knobs'],
};
现在,使用 Knobs 编写您的 stories。
使用 React
import React from 'react';
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
// Add the `withKnobs` decorator to add knobs support to your stories.
// You can also configure `withKnobs` as a global decorator.
// Knobs for React props
export const withAButton = () => (
<button disabled={boolean('Disabled', false)}>{text('Label', 'Hello Storybook')}</button>
);
// Knobs as dynamic variables.
export const asDynamicVariables = () => {
const name = text('Name', 'James');
const age = number('Age', 35);
const content = `I am ${name} and I'm ${age} years old.`;
return <div>{content}</div>;
};
使用 Vue.js
MyButton.story.js
import { storiesOf } from '@storybook/vue';
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import MyButton from './MyButton.vue';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
// Assign `props` to the story's component, calling
// knob methods within the `default` property of each prop,
// then pass the story's prop data to the component’s prop in
// the template with `v-bind:` or by placing the prop within
// the component’s slot.
export const exampleWithKnobs = () => ({
components: { MyButton },
props: {
isDisabled: {
default: boolean('Disabled', false),
},
text: {
default: text('Text', 'Hello Storybook'),
},
},
template: `<MyButton :isDisabled="isDisabled">{{ text }}</MyButton>`,
});
MyButton.vue
<template>
<button :disabled="isDisabled">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
isDisabled: {
type: Boolean,
default: false,
},
},
};
</script>
使用 Angular
import { storiesOf } from '@storybook/angular';
import { boolean, number, text, withKnobs } from '@storybook/addon-knobs';
import { Button } from '@storybook/angular/demo';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
export const withKnobs = () => ({
component: Button,
props: {
text: text('text', 'Hello Storybook'), // The first param of the knob function has to be exactly the same as the component input.
},
});
使用 Ember
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import { hbs } from 'ember-cli-htmlbars';
export default {
title: 'StoryBook with Knobs',
decorators: [withKnobs],
};
export const button = () => ({
template: hbs`
<button disabled={{disabled}}>{{label}}</button>
`,
context: {
label: text('label', 'Hello Storybook'),
disabled: boolean('disabled', false),
},
});
分类
通过为 Knobs 分配 groupId
来对它们进行分类。当存在 groupId
时,Knobs Storybook 面板中会出现选项卡,以便在组之间进行过滤。没有 groupId
的 Knobs 会自动归类到 ALL
组。
export const inGroups = () => {
const personalGroupId = 'personal info';
const generalGroupId = 'general info';
const name = text('Name', 'James', personalGroupId);
const age = number('Age', 35, { min: 0, max: 99 }, personalGroupId);
const message = text('Hello!', 35, generalGroupId);
const content = `
I am ${name} and I'm ${age} years old.
${message}
`;
return <div>{content}</div>;
};
您可以在 Storybook 面板中看到您的 Knobs,如下所示。
可用 Knobs
这些是您可以使用的 Knobs。您可以从 @storybook/addon-knobs
模块导入这些 Knobs。以下是导入 text Knob 的方法。
import { text } from '@storybook/addon-knobs';
就这样,您可以导入以下任何其他 Knobs
text
允许您从用户获取文本。
import { text } from '@storybook/addon-knobs';
const label = 'Your Name';
const defaultValue = 'James';
const groupId = 'GROUP-ID1';
const value = text(label, defaultValue, groupId);
boolean
允许您从用户获取布尔值。
import { boolean } from '@storybook/addon-knobs';
const label = 'Agree?';
const defaultValue = false;
const groupId = 'GROUP-ID1';
const value = boolean(label, defaultValue, groupId);
number
允许您从用户获取数字。
import { number } from '@storybook/addon-knobs';
const label = 'Age';
const defaultValue = 78;
const groupId = 'GROUP-ID1';
const value = number(label, defaultValue);
与 groupId
一起使用时,将默认的 options
作为第三个参数传递。
const value = number(label, defaultValue, {}, groupId);
范围绑定的数字
允许您使用范围滑块从用户获取数字。
import { number } from '@storybook/addon-knobs';
const label = 'Temperature';
const defaultValue = 73;
const options = {
range: true,
min: 60,
max: 90,
step: 1,
};
const groupId = 'GROUP-ID1';
const value = number(label, defaultValue, options, groupId);
color
允许您从用户获取颜色。
import { color } from '@storybook/addon-knobs';
const label = 'Color';
const defaultValue = '#ff00ff';
const groupId = 'GROUP-ID1';
const value = color(label, defaultValue, groupId);
object
允许您从用户获取 JSON 对象或数组。
import { object } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = {
backgroundColor: 'red',
};
const groupId = 'GROUP-ID1';
const value = object(label, defaultValue, groupId);
编辑 knob 中的值时,请确保输入有效的 JSON 语法。
array
允许您从用户获取字符串数组。
import { array } from '@storybook/addon-knobs';
const label = 'Styles';
const defaultValue = ['Red'];
const groupId = 'GROUP-ID1';
const value = array(label, defaultValue);
编辑 knob 中的值时,您需要使用分隔符。默认是逗号,但这可以通过传递分隔符变量来覆盖。
import { array } from '@storybook/addon-knobs'; const label = 'Styles'; const defaultValue = ['Red']; const separator = ':'; const value = array(label, defaultValue, separator);
与 groupId
一起使用时,将默认的 separator
作为第三个参数传递。
const value = array(label, defaultValue, ',', groupId);
select
它允许您从用户获取下拉框中的值。
import { select } from '@storybook/addon-knobs';
const label = 'Colors';
const options = {
Red: 'red',
Blue: 'blue',
Yellow: 'yellow',
Rainbow: ['red', 'orange', 'etc'],
None: null,
};
const defaultValue = 'red';
const groupId = 'GROUP-ID1';
const value = select(label, options, defaultValue, groupId);
选项也可以是数组
import { select } from '@storybook/addon-knobs';
const label = 'Cats';
const options = ['linus', 'eleanor', 'lover'];
const defaultValue = 'eleanor';
const groupId = 'GROUP-ID2';
const value = select(label, options, defaultValue, groupId);
选项也可以是对象数组
const label = 'Dogs';
const arrayOfObjects = [
{
label: 'Sparky',
dogParent: 'Matthew',
location: 'Austin',
},
{
label: 'Juniper',
dogParent: 'Joshua',
location: 'Austin',
},
];
const defaultValue = arrayOfObjects[0];
const groupId = 'GROUP-ID3';
const value = select(label, arrayOfObjects, defaultValue, groupId);
radio buttons
它允许您从用户获取一组单选按钮中的值。
import { radios } from '@storybook/addon-knobs';
const label = 'Fruits';
const options = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const groupId = 'GROUP-ID1';
const value = radios(label, options, defaultValue, groupId);
options
用于从一组选项中选择值的可配置 UI。
import { optionsKnob } from '@storybook/addon-knobs';
const label = 'Fruits';
const valuesObj = {
Kiwi: 'kiwi',
Guava: 'guava',
Watermelon: 'watermelon',
};
const defaultValue = 'kiwi';
const optionsObj = {
display: 'inline-radio',
};
const groupId = 'GROUP-ID1';
const value = optionsKnob(label, valuesObj, defaultValue, optionsObj, groupId);
或者您可以使用此导入方式
import { optionsKnob as options } from '@storybook/addon-knobs';
...
const value = options(label, valuesObj, defaultValue, optionsObj, groupId);
optionsObj
的 display 属性接受
radio
inline-radio
check
inline-check
select
multi-select
files
它允许您从用户获取文件输入的值。
import { files } from '@storybook/addon-knobs';
const label = 'Images';
const accept = '.xlsx, .pdf';
const defaultValue = [];
const groupId = 'GROUP-ID1';
const value = files(label, accept, defaultValue, groupId);
您可以选择指定一个 文件类型列表,文件输入应接受这些类型。可以同时选择多个文件,它们将作为 Data URL 数组返回。
date
允许您从用户获取日期(和时间)。
import { date } from '@storybook/addon-knobs';
const label = 'Event Date';
const defaultValue = new Date('Jan 20 2017');
const groupId = 'GROUP-ID1';
const value = date(label, defaultValue, groupId);
注意:默认值不得更改 - 例如,不要使用
date('Label', new Date())
或date('Label')
。
date
knob 返回选定的日期作为字符串化的 Unix 时间戳(例如 "1510913096516"
)。如果您的组件需要不同格式的日期,您可以包装 date
函数
function myDateKnob(name, defaultValue) {
const stringTimestamp = date(name, defaultValue);
return new Date(stringTimestamp);
}
button
它允许您包含一个按钮和相关的处理程序。
import { button } from '@storybook/addon-knobs';
const label = 'Do Something';
const handler = () => doSomething('foobar');
const groupId = 'GROUP-ID1';
button(label, handler, groupId);
Button knobs 会在处理程序触发后导致 story 重新渲染。您可以通过让处理程序返回 false
来阻止这种情况。
withKnobs 选项
withKnobs 也接受两个可选参数作为 story 参数。用法
import { withKnobs } from '@storybook/addon-knobs';
export default {
title: 'Storybook Knobs',
decorators: [withKnobs],
};
export const defaultView = () => <div />;
defaultView.parameters = {
knobs: {
// Doesn't emit events while user is typing.
timestamps: true,
// Escapes strings to be safe for inserting as innerHTML. This option is true by default. It's safe to set it to `false` with frameworks like React which do escaping on their side.
// You can still set it to false, but it's strongly discouraged to set to true in cases when you host your storybook on some route of your main site or web app.
escapeHTML: true,
},
};
Typescript
如果您使用 Typescript,请确保已安装以下库的类型定义
- node
- react
您可以使用以下命令安装它们:(假设您正在使用 Typescript >2.0.)
yarn add @types/node @types/react --dev