目前社区上,最好的,支持React Native的Living Style Guide工具是getstorybook,本文我们就一起来看看如何用这个工具构建一个Living Style Guide(以iOS模拟器为例)。
安装getstorybook,步骤非常简单,只需要运行命令
npm i getstorybook --save-dev
运行getstorybook,
getstorybook
该命令会在项目根目录下生成一个新的目录storybook, 该目录是一个完整的,独立的React Native应用。
同时为往项目的package.json的scripts中插入一条命令
"scripts": {
...
"storybook": "storybook start -p 7007",
...
},
初始化getstorybook之后,接下来就可以启动storybook了
npm run storybook
该命令会在本地拉起一个服务器提供storybook的目录界面,同时通过React Native的Hot Module Replacement特性完成与模拟器上的应用的通信,把模拟器的当前应用切换到storybook目录下的应用以及后续的通过浏览器操作应用状态都是通过这个特性完成。storybook启动完成之后,你可以通过http://localhost:7007 访问到该界面。因为还没有启动React Native应用,所以目录界面上没有任何内容。接下来,在新的命令行窗口启动react native应用。
npm run run-ios
该命令会启动iOS模拟器,启动好之后,就可以看到如下的界面(注:界面上笔者已经添加了多个UI组件的Demo)
这样,Living Style Guide平台就搭建好了,接下来的工作就是不断在往该平台添加UI组件的Demo。
添加UI组件Demo
往storybook中添加Demo非常简单,下面就是一个关于SearchPage的Demo:
import React from 'react';
import {storiesOf, action} from '@kadira/react-native-storybook';
import SearchPage from '../../../../src/property/components/searchPage';
storiesOf('Property', module)
.add('SearchPage', () => (
<SearchPage request={{place_name:"London"}} isLoading={false} search={action('Search called')}/>
));
从代码上看,只需要简单的三步就可以完成一个Demo:
- import要做Demo的UI组件
- storiesOf定义了一个组件目录
- add添加Demo
在构建项目的storybook时,一些可以帮助我们更有效的开发Demo小Tips:
- 尽可能的把目录结构与源代码结构保持一致,
- 一个UI组件对应一个Demo,保持Demo代码的独立性和灵活性。
- Demo命名以UI组件名加上Demo缀,
- 在组件参数复杂的场景下,可以提供一个fakeData的目录用于存放重用的UI组件Props数据
getstorybook的其它特性
- Decorators: Demo装饰器,可以把UI Demo放到一个容器中获取更加的视觉效果。
const CenterDecorator = (story) => (
<div style={{ textAlign: "center" }}>
{story()}
</div>
);
storiesOf('Button', module)
.addDecorator(CenterDecorator)
.add('with text', () => (
<Button onClick={action('clicked')}>Hello Button</Button>
));
- Actions:事件记录器,记录事件发生时接收到的数据,例子见SearchPageDemo代码。
- Links:UI Demo连接器,通过这个工具可以把多个UI Demo串联起来形成一个User Journey。下例中就把SearchResultsPageDemo和PropertyDetailsPageDemo串联了起来:
import React from 'react';
import {storiesOf, linkTo} from '@kadira/react-native-storybook';
import {properties} from '../fakeData/properties';
import SearchResultsPage from '../../../../src/property/components/searchResultsPage';
storiesOf('Property', module)
.add('SearchResultsPage', () => (
<SearchResultsPage
properties={properties}
rowPressed={linkTo('Property', 'PropertyDetailsPage-1')}/>
));
- specifications和storyshots:测试工具,开发者甚至可以在storybook中直接完成UI的自动化测试。
因为storybook的addon机制,使得storybook能够很容易的扩展,因此,storybook可能支持更多,更有趣的特性,有需要的话,开发者还可以编写自己的addon。
一点遗憾
storybook不支持Hot Reloading,在React Native平台上不支持storybook-addon-knobs,这导致在storybook无法在IDE中修改代码,直接查看到结果,需要reload界面才能看到最新的修改效果。不过,还好React Native reload界面的速度很快。