0%

Storybook初探(Part2)

Part1 我们主要介绍了如何安装使用 Storybook 去编写基础 stories,渲染组件。Part2我们将一起了解如何编写组件文档、维护 stories 自身状态以及 Storybook 的持续部署。

一、讲在前面

关注 Storybook,你会发现 Storybook 团队迭代速度非常快,使用的用户越来越多,github上的 star 也在增长。Storybook 在6月29日发布 v5.1.9,Part2 是基于v5.1.9,由于与之前的 v4.x 的有一些配置不同,可能会遇到版本相关问题,建议将 Storybook 以及相关 addons 升级至 v5.1.9,具体升级教程可以参考这篇文章

二、组件文档

关于文档介绍,其实相关的 addons 有挺多 addon-notes,storybook-readme 以及 addon-info等。在 Part1,我们使用的是 addon-notes, 在 Part2 笔者改用 addon-info,原因在于addon-info 灵活度更高,可配置性强,用户可自定义其样式。我们简单了解下如何配置使用 addon-info。

1. 如何覆盖 addon-info 自带样式

首先,我们需要了解 addon 作用域,当我们在 config.js 文件中装饰 addon , 它将作用于全局stories,如需要对单个 stories 定制不同的样式,我们可以在 stories 添加的时候传递参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { addDecorator, addParameters  } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
addDecorator(withInfo);
addParameters({
info: {
inline: true,
styles: stylesheet => ({
// Setting the style with a function
...stylesheet,
infoBody: {
...stylesheet.infoBody,
padding: '20px 40px 20px'
},
header: {
...stylesheet.header,
h1: {
...stylesheet.header.h1,
// color: 'green',
},
},
}),
}
});

我们只需要通过修改 info 中的 style 字段就可以自定义全局样式,具体如何覆盖原样式,可以参考 addon-info 的原样式文件

2. 自定义生成组件 props

addon-info 会自动识别组件传递的 props 并生成表格,但是精确度还是不够高,并且会将 antd 自带组件 prop 表也会渲染出来,这并不是我们想要的,发现可以通过 TableComponent 配置项自定义 props 表格, propTablesExclude 配置项从 Prop Tables 中排除其它组件,代码如下,读者也可以自定义自己想要的 props 表以及其样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const Red = props => <span style={{ color: 'red' }} {...props} />;

const TableComponent = (propDefinitions) => {
const props = propDefinitions.map(
({ property, propType, required, description, defaultValue }) => {
return (
<tr key={property}>
<td>
{property}
{required ? <Red>*</Red> : null}
</td>
<td>{description}</td>
<td>{propType}</td>
<td>{defaultValue}</td>
</tr>
);
}
);
return (
<table width="90%">
<thead>
<tr>
<th>参数</th>
<th>说明</th>
<th>类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody>{props}</tbody>
</table>
);
};

因为每一个 stories 都需要渲染 prop 表,想着将自定义表这个方法单抽一个组件出来共用,但是会报错,确认过类型没问题后还是行不通,目前只能每个 stories 编写一个 props table。

注意: 由于 addon-info 对 React jsx 语法不友好,在 Story Source 代码 展示中会出现,查找资料之后,发现在 v5.2.0-alpha.30 有该问题的修复,只需要升级至该版本即可。

3. text 配置项

用作描述组件文档信息,支持 markdown 语法,但我觉得其用做组件使用示例或许会更好,因为其支持 ~js 语法,用户可以 copy 组件基础使用代码。

注意:在写入~js 这种语法是会报错的,因为我们在 markdown 中插入代码的时候会调用 syntaxhighlighter, 错误信息:TypeError: Cannot read property ‘defaultText’ of undefined

解决方案: https://github.com/storybookjs/storybook/pull/6016

三、stories 内部状态管理

一开始想到的是使用 redux 做为数据状态管理,但我们在 stories 仅仅需要维护单个组件内部状态,使用 redux 未必有点庞大,笔者使用的是 storybook-state 库,同 redux 一样,我们需要创建一个 store 保存状态和处理更新,我们在 store 中可以添加组件所需属性,通过 State 组件将 store 传递到 UI 组件,通过 store 的 get、set 方法更新数据。基础使用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { State, Store, StateDecorator } from "@sambego/storybook-state";

const store = new Store({
visible: false
});
<State store={store}>
<SlidePane
visible={store.get("visible")}
style={style}
onClose={() => {
action('我该关闭啦')
store.set({
visible: false
})
}}
>
<div>{children}</div>
</SlidePane>
</State>

四、Storybook 部署

如果团队成员想查看 Storybook,值得庆幸的是, 在线部署 Storybook 很容易,Storybook 推荐我们使用 storybook-deployer 工具,将其部署到 github pages 等静态托管服务。这里我们使用 netlify 自动化部署,无需脚本文件即可实现自动编译生成静态网站。

  1. 使用 github、gitlab 账号登录 netlify 网站。从 github、gitlab 导入我们要部署的仓库,在部署设置时,我们需要设置编译打包命令 ( npm run build-storybook ),打包后的静态文件所在目录(storybook-static),即可完成部署。若部署失败可查看日志解决。

  2. 部署成功之后,netlify 会为我们生成一个 netlify.com 的二级域名, 可以自定义二级域名,有需要也可以完全绑定自己的域名。

  3. 持续部署,netlify 检测到 master 分支有 push 操作,则会通知 webhook 触发新的构建和部署。

体验:感觉访问速度和阿里云的 ecs 相比还是有一些差距的,毕竟是免费的。

五、写在最后

到这里,我们已经能够通过 Storybook 搭建我们的 UI 组件库啦 ,但是我们还缺少测试组件,话说没有测试功能的 Storybook 不是完整的 Storybook,私下有通过 jest 搭建测试框架,但是可能由于 jest 配置和 addon-storyshots 的配置有冲突,没能完成。后续随着组件量增加,以及组件复杂度,会完善测试这方面缺陷。

-------------本文结束, 感谢您的阅读-------------