• home > webfront > ECMAS > storybook >

    Storybook入门安装启动

    Author:zhoulujun Date:

    StoryBook是一个可视化的组件展示平台,并为 UI 组件提供 playground 该工具可以让开发者独立的创建可以交互展示的 UI 组件。Storybook入门没有什么好书的,看官方文档即可。本篇粗略地以react简单介绍下

    对于大型的项目,必须面对的就是组件化开发。

    为什么选择StoryBook

    StoryBook是一个可视化的组件展示平台,并为 UI 组件提供 playground. 该工具可以让开发者独立的创建可以交互展示的 UI 组件

    UI 组件独立运行在于 StoryBook 框架无关的环境中,并且无需担心 UI 组件的特殊依赖和需求。

    StoryBook给开发这提供了一个强大的组件开发的生态环境,其中涉及组件的测试、实景展示、文档,以及术语。常见术语解释如下:

    • Addon:类似Plugin,StoryBook中的功能组件以及扩展以Addon形式存在,开发者亦可以自行编写Addon来扩展StoryBook的功能;

    • Story:类似用例,是组件的各种使用场景;

    • Decorator:就是给Story做个包装,可以是样式包装、模块元数据包装、类型包装等。

    • Notes:备注,可以为每个Story设置Notes,支持MarkDown语法。

    如下是常用的Addon:

    • addon-actions:组件操作事件,如click、change

    • addon-links:链接,如某个Story中单击按钮,链接到另一个Story中

    • addon-notes:Story的备注

    • addon-options:调整StoryBook的外观

    • addon-knobs:在页面上改变变量

    storybook的很多功能都是靠插件来实现的

    storybook常用插件安装

    npm add -D @storybook/addon-actions @storybook/addon-notes @storybook/addon-links @storybook/addon-options @storybook/addon-links  @storybook/addon-knobs storybook-addon-specifications @storybook/addon-info storybook-readme

    大多数插件都需要提前注册,在页面中有一个单独的tab来对storybook进行增强。

    添加插件,在.storybook/addons.js添加如下

    import '@storybook/addon-actions/register';
    import '@storybook/addon-notes/register';
    import '@storybook/addon-options/register';
    import '@storybook/addon-links/register';
    import '@storybook/addon-knobs/register';
    // import '@storybook/addon-info/register';
    import 'storybook-addon-specifications/register';

    @storybook/addon-info插件比较特殊,不需要提前注册,它可以显示story的源码,并针对props提供一些文档。

    StoryBook入门项目搭建

    Storybook入门没有什么好书的,看官方文档即可:https://storybook.js.org/docs/basics/writing-stories/

    受伟大墙影响,推荐看国内中文版的:https://www.bookstack.cn/read/learnstorybook-react-zh/6da1274cb7d081bc.md

    如不过会react的,还是以react入门好,毕竟angularJS、Vue都是后面加入的支持。总之在 React 等领域,Storybook 已经很好的证明了自己,引入这个 工具 以后,即便是在普通的项目中,也能帮助开发者逐渐打理出各种低耦合的可复用组件;

    cd storybook-react
    npm init
    npx -p @storybook/cli sb init --type react
    npm i react react-dom  @storybook/react @storybook/addon-knobs babel-loader @babel/core 
    // npx create-react-app storybook-react

    Vue也是一样的

    npm init

    npx -p @storybook/cli sb init --type vue

    npm i @storybook/vue  vue vue-loader vue-template-compiler @babel/core babel-loader babel-preset-vue

    配置StoryBook

    创建storybook 目录  .storybook/config.js  storybook默认配置存在在.storybook文件夹

    import { configure } from '@storybook/react';
    // configure(require.context('../src/stories', true, /\.stories\.js$/), module);
    configure(
        [
            require.context('../src/stories', true, /\.stories\.js$/),
            // require.context('../lib', true, /\.stories\.js$/),
        ],
        module
    );

    创建测试 ../src/button.stories.js

    import React from 'react';
    import { Button } from '@storybook/react/demo';
    export default { title: '组件分类-Button' };
    export const withText = () => <Button>Hello Button</Button>;
    export const orginButton = () => (
        <button><span role="img" aria-label="so cool">Test</span></button>
    );

    增加交互的,代码来自:https://github.com/Red626/storybook-react/

    import React from 'react';
    import { storiesOf } from '@storybook/react';
    import { action } from '@storybook/addon-actions';
    import { linkTo } from '@storybook/addon-links';
    import LinkTo from '@storybook/addon-links/react';
    import { withKnobs, text, boolean, number, color } from '@storybook/addon-knobs';
    
    storiesOf('Select', module)
        .add('Index', () => (
            <select value="Index" onChange={linkTo('Select', e => e.currentTarget.value)}>
                <option>Index</option>
                <option>First</option>
                <option>Second</option>
                <option>Third</option>
            </select>
        ))
        .add('First', () => <LinkTo story="Index">Go back</LinkTo>)
        .add('Second', () => <LinkTo story="Index">Go back</LinkTo>)
        .add('Third', () => <LinkTo story="Index">Go back</LinkTo>);
    
    storiesOf('Storybook Knobs', module)
        .addDecorator(withKnobs)
        .add('with a button', () => {
            const disabled = boolean('Disabled', false);
            // const  Label = text('label','')
            return (
                <button
                    disabled={disabled}
                    className={disabled ? 'disabled' : ''}
                >
                    {text('Label', `abc${disabled ? '(disabled)' : ''}`)}
                </button>
            );
        })
        .add('as dynamic variables', () => {
            const name = text('Name', 'Arunoda Susiripala');
            const age = number('Age', 89);
            const content = `I am ${name} and I'm ${age} years old.`;
            return (<div>{content}</div>);
        })
        .add('with color', () => {
            const label = 'Color';
            const defaultValue = '#ff00ff';
            const value = color(label, defaultValue);
            return (<div style={{ color: value }}>{value}</div>);
        });

    在package.json  package.json,scripts 增加: 

     "scripts": {
        "storybook": "start-storybook -p 6006",
        "build-storybook": "build-storybook -c .storybook -o .out"
      }

    不必赘述,按照官方操作不走,试了了vue和react,没有发现任何问题

    storybook经验总结

    story 位置放哪儿

    为了维护方便,一般与component平级,如组件目录为:'./src/components';则 story 目录最好为:'./src/stories'

    添加 story,使用 add 添加

    // param1 表示 story 名称,会显示在侧边栏;
    // func 是一个返回待测试组件的函数
    add(param1,func)

    动态加载 story,借用了 webpack 的 context API

    // .storybook/config.js
    import { configure } from '@storybook/react';
    const req = require.context('../src/stories', true, /\.js$/);
    function loadStories() {
        req.keys().forEach(filename => req(filename));
    }
    configure(loadStories, module);

    使用装饰器

    同一个组件可对应多个story,装饰器的作用是把这些 story 包起来,形成一个父级元素,然后可以对这个父级元素做些修饰,比如让所有子元素居中对齐。/react-storybook/stories/2-Pagintion.stories.js

    import React from 'react'
    import { storiesOf } from '@storybook/react'
    import { withKnobs, number } from '@storybook/addon-knobs'
    import Pagination from '../src/component/Pagination/Pagination'
    import paginationDoc from '../src/component/Pagination/readme.md'
    
    export default {
        title: 'Pagination',
    }
    storiesOf('Custom UI', module)
        .addDecorator(story => <div style={{ textAlign:'center',marginTop: '50px' }}>{story()}</div>)
        .addDecorator(withKnobs)
        .add('Pagination', () => {
            const totalPage = number('totalPage', 100)
            const page = number('currentPage', 45)
    
            return (<Pagination totalPage={totalPage} page={page} pageSize={10}/>)
        }, {
            notes: { markdown: paginationDoc },
        })

    Pagination组件测试 /react-storybook/src/component/Pagination/Pagination.js

    /**
     * Authour: zhoulujun.cn
     * Date: 2020-02-21 14:51
     **/
    import React from 'react'
    
    class Pagination extends React.Component {
        constructor (props) {
            super(props)
            this.state = { currentPage: 1 }
            this.nextPage = this.nextPage.bind(this)
        }
        render () {
            let { totalPage, pageSize, page } = this.props
            return (
                <div>
                    total:{totalPage},pageSize:{pageSize},currentPage:{page}
                </div>
            )
        }
    }
    
    export default Pagination


    推荐与参考文章:

    使用storybook管理React组件 https://imweb.io/topic/5c0d3e6a611a25cc7bf1d7fe

    StoryBook 使用指南 https://www.jianshu.com/p/9cb75ae50515

    StoryBook实战 (angluarJS) https://blog.dteam.top/posts/2019-06/storybook实战.html

    手摸手教你用 Storybook 改善组件库的开发(Vue) https://juejin.im/post/5cd6dd94e51d453a8f348bef


    转载本站文章《Storybook入门安装启动》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/storybook/8316.html