StoryBook 开发 React 组件库文档

说明

StoryBook 是一个开源的 UI 组件库构建工具,支持 React、Vue、Angular 等主流开发框架,使用 StoryBook 将获得以下优势:

  1. 开发环境隔离并以可交互的方式展示组件
  2. 便捷且直观组件分组管理方式
  3. 同样使用 webpack 构建,集成 react-hot-loader 调试方便
  4. 可配置化程度高,插件化,社区完善

安装

# 安装主要依赖
npm install @storybook/react --save-dev

# 然后安装开发组件必要的package react react-dom babel-loader @babel/core 等


# 如果需要用到插件
npm install @storybook/addons --save-dev

# package.json 增加 scripts {"storybook": "start-storybook"}
# 启动项目
npm run storybook

将 StoryBook 集成到项目中

# 目录说明
├── .storybook/ # 配置文件目录
├  ├── addons.js # 插件注册文件
├  ├── .babelrc # 自定义 babel 配置
├  ├── config.js # 主配置文件
├  ├── customTheme.js # 自定义的主题
├  ├── layout.js # 主显示区域的布局
├  └── webpack.config.js #自定义 webpack 配置

1. 创建配置文件目录

在根文件夹下创建 .storybook/ 文件夹,StoryBook 的所有配置相关的文件都会放到这里

mkdir .storybook
2. 创建主配置文件

在 .storybook/ 下创建 config.js 配置文件,这里主要负责全局的一些配置,例如:

  • 页面主题配置
  • 插件安装
  • 收集待展示的 stories (概念稍后说明)

注意:如 addParameters、addDecorator 在 .storybook/config.js 中进行的都是全局的操作,适用于全部的 story, 如果只应用于特定的 story 可以在 story 中进行配置

// .storybook/config.js

import { configure, addParameters, addDecorator } from '@storybook/react';
import {withInfo} from '@storybook/addon-info';
import customTheme from './customTheme';


// 1.
function loadStories() {
  const req = require.context('../src/components', true, /\.stories\.js$/);
  req.keys().forEach(filename => req(filename));
}


addParameters({
  // 2.
  options: {
    showPanel: true,
    panelPosition: 'right',
    theme: customTheme
  },
});

addDecorator(withInfo);
addDecorator(AreaWrapper)

configure(loadStories, module);

1. loadStories Function

是一个用来加载 stories 的函数

2. addParameters

追加参数,其值是一个对象,其中 key 为 options 的项是默认支持的,用来配置一些原有控件的展示情况,更多可查看Options Parameter

如果使用了某些插件,可能也需要通过 addParameters 方法追加参数 例如 storybook-readme 这个插件,可以追加参数来改变readme 中代码的展示主题

addParameters({
  options: {
    // ...
  },
  readme: {
    codeTheme: 'hopscotch',
  }
});
3. addDecorator

Decorator 是一个通用的包装组件的方式,许多插件的应用需要实现对组件的包装,我们也可以通过这个方法,实现对组件的包装,例如:增加边距,美化显示效果

const AreaWrapper = (storyFn) => (
  <div style={{padding: '10px 20px'}}>
    {storyFn()}
  </div>
);

addDecorator(AreaWrapper)
4. 主题

内置 light 和 dark 两个主题,如果有定制化需要可以通过如下方式创建,更多查看Theming Storybook

import { create } from '@storybook/theming';

export default create({
  base: 'light',
  //...
  brandTitle: 'XXX UI COMPONENTS',
  brandUrl: 'https://xxx.xxx.com',
  brandImage: 'https://cdn.xxx.com/common/static/img/Logo.svg'
});
3. 编写 story

story 就是”描述“,用来描述一个组件的使用流程,我们在 .storybook/config.js 中通过 loadStories 加载了指定的描述文件,现在我们来编写它

// src/components/LoadingButton/index.stories.js

import * as React from 'react';
import {storiesOf} from '@storybook/react';
// 引入插件
import {withKnobs} from '@storybook/addon-knobs';
// 引入组件
import {LoadingButton} from 'xxx-ui-components';

// 创建一个 story
storiesOf('Button/LoadingButton', module)
  // 加插件
  .addDecorator(withSmartKnobs)
  .addDecorator(withKnobs)
  // 加参数
  .addParameters({
    readme: {
      content: ButtonReadme,
      sidebar: ButtonUSAGE
    },
  })
  // 加案例
  .add('with text', () => {
    return (
      <LoadingButton
        loading={false}
        label={'sxxx'}
        arr={array('arr', [])}
        immutable={Immutable(object('immutable'))}
        onClick={linkTo('XXX/Button', 'with emoji')}
      >
        Hello Button
      </LoadingButton>
    );
  })
  .add('with emoji', () => <BlankPage type={'NOT_FOUND'} />, {
    options: { panelPosition: 'right' } // 可以有 第三个参数与 addParameters 类似,给每一个案例定制
  });

4. 增加 addons

story 创建中会用到插件 addons, storybook 官方提供一部分插件,其他的是社区提供的

1. 注册插件

首先要在 .storybook/ 下创建 addons.js 插件注册文件,在这里是进行插件注册的,(并不是所有插件都需要注册,具体的要看插件的文档要求)

// .storybook/addons.js

import '@storybook/addons'
import '@storybook/addon-knobs/register';
import 'storybook-readme/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-storysource/register';
import '@storybook/addon-a11y/register';
import '@storybook/addon-viewport/register';
import '@storybook/addon-links/register';
2. 插件配置

大部分插件可以选择是在全局安装还是在某一个 story 中安装

  • 全局安装:.storybook/config.js 中通过 addDecorator(addon) 安装
  • story安装:在某个 *.stories.js 中 storiesOf(‘XXX’, module).addDecorator(addon) 安装

同理,部分插件还需要进行参数的配置 这就会用到 addParameters() 方法

  • 全局安装:.storybook/config.js 中通过 addParameters({[addonKey]: addonParam}) 追加
  • story安装:在某个 *.stories.js 中 storiesOf(‘XXX’, module).addParameters({[addonKey]: addonParam}) 追加
5. 自定义构建

有的时候,我们想对打包构建做一些定制化的处理就需要更改 storybook 的 webpack | babel 配置,storybook 提供更改的接口

1. 自定义 .babelrc

在 .storybook/ 下创建 .babelrc 即可,他会覆盖 storybook 默认的babel 配置

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "node": "current",
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "flow",
    "react",
    "stage-2"
  ],
  "plugins": [
    "react-hot-loader/babel",
    ["import", [
      { "libraryName": "antd", "libraryDirectory": "es", "style": true }
    ]]
  ]
}

2. 自定义 webpack

在 .storybook/ 下创建 webpack.config.js 文件,与一般的 webpack 配置文件不同, 因为 storybook 本身已经实现了一套 webpack 配置,你需要做的是对其修改而不是重新写一套

  1. webpack 使用的是 4.x.x 版本
  2. config 文件的返回值是一个异步函数
  3. 异步函数接收两个参数 config:默认配置 mode 环境变量
  4. config 的 entry 与 output 不应该被更改
module.exports = async ({config, mode}) => {
  config.resolve.extensions.push('.css');
  config.resolve.modules.push(path.resolve(__dirname, '../src'));
  config.module.rules.push({
    test: /\.stories\.jsx?$/,
    loader: require.resolve('@storybook/addon-storysource/loader'),
    enforce: 'pre',
    options: { parser: 'flow' },
  });
  config.plugins.push(
    new webpack.ProvidePlugin({
      React: 'react',
      _: 'lodash'
    })
  );

  return config
};

Logo

前往低代码交流专区

更多推荐