想写出复用性强的组件?快来试试 Storybook 吧!

lxf2023-04-13 21:01:01

持续创作,加速成长!这是我参与「AdminJS · 10 月更文挑战」的第6天,点击查看活动详情

前言

最近笔者通过学习和使用 Storybook 时,记录了一些使用心得,写下这篇文章和大家分享一下,笔者主要通过官方文档进行学习:Storybook官方文档

简介

StorybookUI 组件的开发环境,它允许开发者浏览组件库,查看每个组件的不同状态,以及交互地开发和测试组件。

Storybook 可帮助你记录组件以供重用,并自动对组件进行可视化测试以防止出现错误。

开始

在对 Storybook 有了大致的了解之后,下面就让我们把 Storybook 启动起来吧!

Storybook 需要安装到已经设置了框架项目中。它不适用于空项目。这里我使用的是 React,首先我们进入空项目安装 React,这里推荐使用官方脚手架安装:

npx create-react-app my-app

安装完成后进入项目目录:

cd my-app

之后再安装 Storybook,命令如下:

npx storybook init

安装完成后将 Storybook 启动:

npm run storybook

启动成功后,页面如下:

想写出复用性强的组件?快来试试 Storybook 吧!

在该项目的 src 下,我们可以看到 stories 文件夹,里面有一些后缀为 .stories.jsx 的文件,分别对应着页面中的 ButtonHeaderPage 组件。这些 story格式 (CSF) 编写——这是一种基于 ES6 模块的标准,用于编写组件示例。

组件

我们以 Button 组件为例进行分析,默认情况下,页面上的 Button 组件如下图:

想写出复用性强的组件?快来试试 Storybook 吧!

可以看到 Canvas 部分用来实时显示组件,Controls 用来控制组件,例如可以改变按钮的背景颜色、大小等。当我们点击按钮时,在 Actions 中会打印点击事件,如下图显示:

想写出复用性强的组件?快来试试 Storybook 吧!

现在我们大致清楚了 Storybook 是可以对组件进行一些调试的,那么如果我们需要设计一些可以高度复用的组件,该怎么通过 Storybook 来设计呢?

对于开发者来说,设计出高度复用的组件可以为以后的开发节约大量的时间,写出更优质的组件,这样的组件具有高内聚、低耦合的特点,在大型项目中写出这样的组件则显得尤为重要!

在需求中,设计按钮组件时,有固定因素和可变因素,例如按钮的大小,颜色以及按钮的内容等等都是可变因素;固定因素有比如按钮的背景图片。保留固定元素将可变因素进行动态转化可以达到组件高度重用的目的。

Button.stories.jsx 中,我对默认代码进行了修改,通过 args 对组件 Button 进行传参,为了方便理解,其中 args 只包括了 primarylabel 两个参数(即是否为主要按钮和按钮内容),代码如下:

import React from 'react';

import { Button } from './Button';

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
  title: 'Example/Button',
  component: Button
};

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Primary.args = {
  primary: true,
  label: 'Button'
};

Template.bind({}) 是一个标准 JavaScript 技术用于制作函数的副本。我们复制它,Template 让每个导出的 story 都可以在其上设置自己的属性。

通过将 args 引入组件的 story 中,不仅可以减少代码量,而且还减少了数据重复。

Button.jsx 中,我们将传入的参数进行解构,这里直接解构出 primarylabel,对其做了类型约束:

import React from 'react';
import PropTypes from 'prop-types';
import './button.css';

/**
 * Primary UI component for user interaction
 */
export const Button = ({ primary, label }) => {
  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
  return (
    <button
      type="button"
      className={['storybook-button', `storybook-button--medium`, mode].join(' ')}
    >
      {label}
    </button>
  );
};

Button.propTypes = {
  /**
   * Is this the principal call to action on the page?
   */
  primary: PropTypes.bool,
  /**
   * Button contents
   */
  label: PropTypes.string.isRequired
};

Button.defaultProps = {
  primary: false
};

页面如下图:

想写出复用性强的组件?快来试试 Storybook 吧!

可以看到,Controls 中只保留了 primarylabel,这是因为我只对这两个参数进行了相关操作(定义、传递以及类型约束)。通过这样的方法,把可变因素当作参数进行传递,组件的复用性是不是大大提高了呢,其实还可以进一步提高,从上述代码来看 Button 组件的样式是写在其他文件的,我们可以把样式写在 Button.jsx 中,这样一个文件就对应了一个组件,便于管理。样式编写我使用的是 Emotion,能够实现 css in js,官方地址如下:Emotion,推荐使用 @emotion/styled

通过这种方法来编写组件,追求高复用性,养成一种编写优质代码的习惯,是不是非常的nice呢!

总结

以上就是笔者在阅读文档以及使用 Storybook 后的一些记录,也是笔者对 Storybook 的一些个人见解,如有不足欢迎大家指出,如果大家觉得还可以的话,不要忘了点赞哟~,谢谢!