Storybook"/>
Storybook
Storybook 是一个 ui 组件开发管理的工具,我们可以通过 story 独立创建组件,并且每个组件都有一个独立开发调试环境。Storybook 是运行在主应用程序之外,不依赖于项目,因此我们不必担心开发环境、依赖等问题导致不能开发组件。 Storybook 支持多个主流框架(React, Vue, Angular, Mithril, Ember)等,由于目前笔者使用的是 react 技术栈,本文将介绍 react 项目如何配置使用 Storybook。
一. 操作指南
1. 首先,安装@storybook/react,react, react-dom, babel-core 等项目所需基础库。在 package.json 文件中添加 "storybook": "start-storybook -p 9001 -c .storybook"2. 新建文件,先看下项目目录结构
.storybook 文件夹存放 storybook 配置,及插件文件。
src/components 存放 UI 组件。
src/markdown 存放组件显示的文档等介绍。
src/stories 存放 story,story 可绑定相应的组件,一个组件可以有多个不同状态的 story。
3. 编写 story
添加 storybook 配置文件
.config 配置文件
import { conp, addDecorator } from '@storybook/react';
import { withOptions } from '@storybook/addon-options';
import { withNotes } from '@storybook/addon-notes';
import { themes } from '@storybook/components';
// 全局加载装饰器
// addDecorator(story => <div style={{ textAlign: 'center' }}>{story()}</div>);
addDecorator(
withOptions({
// name: 'Foo',
// theme: themes.dark
showSearchBox: false,
showAddonsPanel: true,
addonPanelInRight : true,
enableShortcuts : true,
})
)
addDecorator(withNotes);
/**
* 动态加载所有stories
*/
const req = require.context('../src/stories', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach(fileName => req(fileName));
}
configure(loadStories, module);
这里为了动态加载 stories,Storybook 使用了 Webpack 的 require.context 动态加载模块。
添加 UI 组件(src/components/circle)
import React from 'react'
import './style.scss'
export function Circle (props) {
const defaultClass = 'circle_default';
const { className, ...other } = props;
return (
<div
className={`${defaultClass} ${className} `}
{...other}
>
{props.children || ''}
</div>
)
}
添加 story(src/stories/circle.stories.js)
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { withKnobs, text, boolean, number, object } from '@storybook/addon-knobs';
import { Circle } from '../components/circle';
import '../components/circle/circle-color.scss';
import circleText from '../markdown/circle.md';
const stories = storiesOf('Circle', module);
// 动态修改react组件属性(测试)
// 可在config文件中全局配置
stories.addDecorator(withKnobs);
stories.add('圆点', () => (
<div>
<div>
<Circle className='status_running' onClick={action('clicked')}></Circle>
运行中
</div>
<div>
</Circle>
成功
</div>
<div>
</Circle>
取消
</div>
<div>
</Circle>
运行失败
</div>
<div>
</Circle>
提交中
</div>
<div>
</Circle>
提交失败
</div>
<div>
</Circle>
上游失败
</div>
<div>
</Circle>
冻结
</div>
<div>
</Circle>
已停止
</div>
<div>
</Circle>
重试中
</div>
<div>
</Circle>
等待提交
</div>
</div>
), {
notes: {
markdown: circleText
}
});
stories.add('动态修改style', () =>{
const groupId = 'circle';
const defaultStyle = {
background: 'black'
}
const style = object('Style', defaultStyle, groupId);
return <Circle style={style} ></Circle>
}
)
注意:1. storybook 插件都需要在 ./stroybook/addons.js 中注册才能使用,注册完之后需要重新运行项目。2. 这里有一个问题,在引入 markdown 作为组件文档时,其中表格渲染 border 无法显示。3. storybook 内部集成的 webpack 不支持 scss 类型文件。需要自定义 webpack,这里我们在原来的配置基础上实现。
const path = require("path");
// 保留storybook原有默认配置 + 扩展配置
module.exports = function (baseConfig, env, defaultConfig) {
defaultConfig.module.rules.push({
test: /\.stories\.js$/,
loaders: [require.resolve('@storybook/addon-storysource/loader')],
enforce: 'pre',
}, {
test: /.(scss|sass)$/,
loaders: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "../")
});
return defaultConfig;
};
npm run storybook 查看效果
二. 插件
storybook 的插件有许多,基本上有两种类型(装饰器 Decorators 和原生插件 Native Addons) Decorators 通过封装 react 组件实现,比如 storybook-router。 Native Addons 主要是以面板的形式注入,便于管理使用组件,比如 addon-actions 等。 本文主要介绍几个常用的 addons,目前项目中使用到的 addons 有:
import '@storybook/addon-storysource/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-options/register';
1. addon-storysource
此插件主要是在插件面板中显示 story 源代码
安装插件之后需要在 webpack 中定义,让其在每个 story 都生成一个装饰者调用。
module.exports = function (baseConfig, env, defaultConfig) {
defaultConfig.module.rules.push({
test: /\.stories\.jsx?$/,
loaders: [require.resolve('@storybook/addon-storysource/loader')],
enforce: 'pre',
});
return defaultConfig;
};
并且可以在 options 选项中定义 printWidth 等更多优化配置格式化面板。
2. addon-knobs
import React from 'react';
import { storiesOf } from '@storybook/react';
import SlidePanel from '../components/slidePanel';
import { boolean, object, text } from '@storybook/addon-knobs';
storiesOf('SlidePanel', module)
.add('基本用法', () =>{
const groupId = 'slidepanel'
const defaultStyle = {
right:'-20px',
width:'80%',
minHeight: '600px',
height: '100%'
}
const style = object('style', defaultStyle, groupId);
const defayltText = 'hello slidePanel'
const children = text('children', defayltText, groupId)
return <SlidePanel
visible={boolean('visible', true, groupId)}
style={style}
onClose={()=>{
console.log('click')
}}
>
<div>{children}</div>
</SlidePanel>
})
我们在这个 story 中定义了 style、visible、children 三个动态变量传入 SlidePanel 组件,其变量类型分别对应的是 boolean、object、text。在 knob 中还可以导入许多的类型约束(number, color, array)等。
注意:在定义动态变量时,可以通过 groupId 来分类不同组件的变量,在选项卡中将会以 groupId 在组中过滤,没有参入 groupId,将会自动分类到 All 组中。
3. addon-actions
actions 可以用于显示 storybook 事件处理程序接收的数据(多个事件触发可以写成对象形式)
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action, actions, configureActions , decorate } from '@storybook/addon-actions';
import { Button } from '../components/button';
// 多个动作触发
const events = actions({
onClick: 'clicked',
onMouseOver: 'hovered'
})
// const firstArg = decorate([args => args.slice(0, 1)]);
storiesOf('Button', module)
.addDecorator(story => <div style={{ textAlign: 'center' }}>{story()}</div>) // 当前组件加载装饰器
.add('基本用法', () => (
<Button {...events}>123</Button>
))
4. addon-notes
可以在面板中添加 story 注释文本信息。
addon-notes 只允许在面板中显示信息,有时候不方便我们查看组件 api 等详细信息。如果我们想要在组件旁边显示用法以及其他类型的文档介绍等信息,可以安装 addon-info(组件文档管理必备)。
storybook 提供了许多 addons。
storybook-state: 添加 state 面板,展示或更新 state,重绘视图。
storyShots: 快照测试。
storybook-readme: 将 markdown 导入为 story 等。
更多插件介绍详情官网 storybook.js.org/addons
三. 写在后面
这篇文章简单介绍了如何基础使用 storybook 工具集成显示 ui 组件,总体感觉是学习成本不算高。为了后期有便于更好的维护组件,有信心的提交代码,那测试功能必不可少。并且目前不能直接在 story 中修改 react 组件 state。下篇文章我们将集成 redux 便于管理数据,详细叙述 storybook 是如何利用基于 jest 的 addons 进行一系列的自动化测试以及手动测试。
更多推荐
Storybook
发布评论