storybook让组件自动形成好看的文档~
storybook 是什么
storybook 是一个 JS 库,可以在已有项目,在无需修改业务逻辑的情況下,给组件自动形成文档,可很好的展示属性和功能。
怎么安装
在已有的项目里,一行命令安装
npx storybook init
此时项目里增加了一些文件:
.storybook
文件夹,里面是配置src/stories
,展示组件,我们的重点package.json
会多两个命令,
- "storybook": "start-storybook -p 6006 -s public",
- "build-storybook": "build-storybook -s public"
先运行起来,看看
npm run story
开始写 story
第一步,像平时一样,写组件。
比如这边,来个Button.jsx
import PropTypes from 'prop-types'; const Button = ({ label, backgroundColor = 'red', onClick }) => { return ( <button style={{ backgroundColor, color: '#fff' }} onClick={onClick}> {label} </button> ); }; Button.propTypes = { label: PropTypes.string, backgroundColor: PropTypes.string, onClick: PropTypes.func, }; export default Button;
第二步,新建Button.stores.jsx
import Button from './Button'; export default { title: 'Button', // 标题 component: Button, // 哪个组件 }; // 组件展示的例子 export const Red = () => <Button label="red" backgroundColor="red" />; export const Blue = () => <Button label="blue" backgroundColor="blue" />;
title
有路径的话,自动在左侧菜单形成文件夹。
此时,重新访问网址
网络异常,图片无法展示
|
网络异常,图片无法展示
|
propTypes
增加 - Controls 动态修改属性显示
展示的两个例子,并不能修改,其实可以升级,在页面随时编辑,随时显示。 其实很简单,将上面的代码微改造下
import Button from './Button'; export default { title: 'Button', // 标题 component: Button, // 哪个组件 }; // 先写模版 const Template = (args) => <Button {...args} />; // 写例子,例子的模版都是一样的,只是属性不一样 // Template.bind({}) is a standard JavaScript technique for making a copy of a function. We copy the Template so each exported story can set its own properties on it. export const Red = Template.bind({}); Red.args = { label: 'red', backgroundColor: 'red', }; export const Blue = Template.bind({}); Blue.args = { label: 'blue', backgroundColor: 'blue', };
网络异常,图片无法展示
|
增加 - Actions 事件用法
上面都是属性,现在增加事件onClick
。
const Button = ({ label, backgroundColor = 'red', onClick }) => { return ( <button style={{ backgroundColor, color: '#fff' }} onClick={onClick}> {label} </button> ); }; Button.propTypes = { label: PropTypes.string, backgroundColor: PropTypes.string, onClick: PropTypes.func, }; export default Button;
看下配置文件,发现当属性以on
开头的话,会自动识别为action
如果不以on
开头的话,需要额外说明。
const Button = ({ label, backgroundColor = 'red', handleClick }) => { return ( <button style={{ backgroundColor, color: '#fff' }} onClick={handleClick}> {label} </button> ); }; Button.propTypes = { label: PropTypes.string, backgroundColor: PropTypes.string, handleClick: PropTypes.func, }; export default Button;
想要示例里,按钮能绑定事件的话
export default { title: 'Button', // 标题 component: Button, // 哪个组件 argTypes: { handleClick: { action: 'handleClick' } }, };
增加 - children 的处理
这边简单增加一个布局组件,体验下children
的处理。
import PropTypes from 'prop-types'; const Stack = ({ children, direction = 'row', spacing = 2 }) => ( <div style={{ display: 'flex', gap: spacing + 'px', flexDirection: direction }} > {children} </div> ); Stack.propTypes = { spacing: PropTypes.number, direction: PropTypes.oneOf(['row', 'column']), }; export default Stack;
感觉还是很普通的。 来个文档:
import Stack from './Stack'; export default { title: 'Stack', // 标题 component: Stack, // 哪个组件 argTypes: { countOfChild: { type: 'number', defaultValue: 3 }, }, }; // 先写模版 const style = { display: 'flex', width: '50px', height: '50px', alignItems: 'center', justifyContent: 'center', backgroundColor: '#f69', color: '#fff', }; const Template = ({ countOfChild, ...args }) => ( <Stack {...args}> {new Array(countOfChild).fill('').map((_, index) => ( <div style={style} key={index}> {index + 1} </div> ))} </Stack> ); export const Horizontal = Template.bind({}); Horizontal.args = { direction: 'row', spacing: 10, }; export const Vertical = Template.bind({}); Vertical.args = { direction: 'column', spacing: 10, };
argTypes 的属性,只是添加到示例里面,来方便示例的展示,跟真实的组件属性没有关系。
网络异常,图片无法展示
|
网络异常,图片无法展示
|
Vue 类项目添加 storybook
上面步骤基本一致,唯一不同的就是组件的写法,不一致。 Button.vue:
<template> <button type="button" @click="onClick" :style="{ backgroundColor, color: '#fff' }" > {{ label }} </button> </template> <script> export default { name: 'Button', props: { label: { type: String, required: true, }, backgroundColor: { type: String, default: '#f69', }, }, methods: { onClick() { this.$emit('onClick'); }, }, }; </script>
Button.stories.js:
import Button from './Button'; // More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export export default { title: 'Button', component: Button }; // More on component templates: https://storybook.js.org/docs/vue/writing-stories/introduction#using-args const Template = (args, { argTypes }) => ({ props: Object.keys(argTypes), components: { Button }, template: '<Button @onClick="onClick" v-bind="$props" />' }); export const Red = Template.bind({}); Red.args = { label: 'Red', backgroundColor: 'red' }; export const Blue = Template.bind({}); Blue.args = { label: 'Blue', backgroundColor: 'blue' };
Stories 部署访问
先运行命令:
# npm run build-storybook yarn build-storybook
根目录下会多一个文件夹storybook-static
,部署即可,本地可以进到目录,然后anywhere 9000
即可访问