关于react.js:使用dumi搭建UI组件库

34次阅读

共计 4287 个字符,预计需要花费 11 分钟才能阅读完成。

什么是 dumi

dumi,中文发音嘟米,是一款为组件开发场景而生的文档工具,与 father 一起为开发者提供一站式的组件开发体验,father 负责构建,而 dumi 负责组件开发及组件文档生成。

个性

  1. 📦 开箱即用,将注意力集中在组件开发和文档编写上
  2. 📋 丰盛的 Markdown 扩大,不止于渲染组件 demo
  3. 🏷 基于 TypeScript 类型定义,主动生成组件 API
  4. 🎨 主题轻松自定义,还可创立本人的 Markdown 组件
  5. 📱 反对挪动端组件库研发,内置挪动端高清渲染计划
  6. 📡 一行命令将组件资产数据化,与上游生产力工具串联

环境筹备

首先得有 node,并确保 node 版本是 10.13 或以上。

$ node -v
v10.13.0

初始化脚手架

创立空文件夹
mkdir dumi-ui-site-template

初始化一个站点模式的组价库开发脚手架

$ yarn create @umijs/dumi-lib --site

运行

执行 npm run dev 或 npx dumi dev 即可开始调试组件或编写文档。

执行成果如下:

开发一个 button 组件

src 上面创立文件 Button 文件。

外围代码

index.tsx

import React, {useState} from 'react';
import styled from 'styled-components';
import clsx from 'clsx';
import * as vars from '../styles/vars';
import {isMobile} from '../utils/dom';
import {getThemeColorCss} from '../styles/themeHelper';
type Props = {
  /** default 线框,primary 实色框 */
  type?: 'default' | 'primary';
  /** 线框应用主题色 */
  active?: boolean;
  /** 禁用 */
  disabled?: boolean;
  /** 自定义 style */
  style?: React.CSSProperties;
  /** 按钮类型 */
  htmlType?: 'submit' | 'reset' | 'button' | undefined;
  /** 块级按钮 */
  block?: boolean;
  children?: React.ReactNode;
  /** 自定义 className */
  className?: string;
  /** 圆形按钮 */
  circle?: boolean;
  /** 虚线边 */
  dashed?: boolean;
  /** 设置危险按钮 */
  danger?: boolean;
  /** 设置为展现的标签,比方 div,a,button */
  as?: any;
  /** 设置按钮的图标组件 */
  icon?: React.ReactNode;
  /** 设置按钮加载状态 */
  loading?: boolean;
  /** 是否幽灵按钮 */
  ghost?: boolean;
  /** 点击回调 */
  onClick?: (e: React.SyntheticEvent) => void;
  /** 点击后,下次能点击的工夫距离,避免反复点击, 如果是 true, 距离默认是 1s  */
  wait?: number | boolean;
};

const StyledButton = styled.button`
  color: inherit;
  cursor: pointer;
  margin: 0;
  display: inline-flex;
  box-sizing: border-box;
  outline: 0;
  position: relative;
  align-items: center;
  user-select: none;
  vertical-align: middle;
  justify-content: center;
  text-decoration: none;
  background-color: transparent;
  appearance: none;
  -webkit-tap-highlight-color: transparent;

  font-weight: 400;
  white-space: nowrap;
  background-image: none;
  transition: all 0.3s ease;
  user-select: none;
  touch-action: manipulation;
  padding: 4px 16px;
  font-size: 14px;
  border-radius: 2px;
  border: 1px solid transparent;
  height: 32px;

  &.default {
    background-color: #fff;
    border-color: ${vars.border};

    ${isMobile ? '&:active' : '&:hover'} {opacity: 0.8;}

    &.pc:hover,
    &.active {${getThemeColorCss('border-color')}
      ${getThemeColorCss('color')}
    }

    &.mobile:active {background-color: ${vars.activeBg};
    }

    &.danger,
    &.danger:hover,
    &.danger:active {color: ${vars.danger};
      border-color: ${vars.danger};
    }
  }

  &.primary {${getThemeColorCss('background-color')}
    ${getThemeColorCss('border-color')}
    color: #fff;

    ${isMobile ? '&:active' : '&:hover'} {opacity: 0.8;}

    &.danger,
    &.danger:hover,
    &.danger:active {background-color: ${vars.danger};
      border-color: ${vars.danger};
    }
  }

  &.disabled,
  &.disabled:hover,
  &.disabled:active {
    cursor: not-allowed;
    opacity: 0.6;
    pointer-events: none;
  }

  &.block {width: 100%;}

  &.circle {
    min-width: 32px;
    padding: 0;
    border-radius: 50%;
  }

  &.dashed {border-style: dashed;}

  &.ghost,
  &.ghost:hover {color: ${vars.border};
    background-color: transparent;
    border-color: ${vars.border};
  }

  &.anchor {
    margin: unset;
    padding: unset;
    background: unset;
    border: none;
    ${getThemeColorCss('color')}
    height: unset;
  }
`;
const Button = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
  const {
    children,
    type = 'default',
    disabled,
    block,
    active,
    danger,
    circle,
    dashed,
    loading,
    ghost,
    className,
    htmlType,
    onClick,
    wait,
    ...rest
  } = props;

  return (
    <StyledButton
      {...rest}
      ref={ref}
      disabled={disabled}
      type={htmlType}
      className={clsx(
        'uc-btn',
        type,
        {
          disabled: disabled || loading,
          block: block,
          danger: danger,
          circle: circle,
          dashed: dashed,
          ghost: ghost,
          pc: !isMobile,
          anchor: rest.as === 'a',
          active,
        },
        className,
      )}
    >
      {children}
    </StyledButton>
  );
});

Button.displayName = 'UC-Button';

export default Button;

index.md

---
title: Button 按钮
order: 0
group:
  title: 根底组件
nav:
  title: '组件'
  path: /components
---

## Demo

<code src="../../demo/Button/index.jsx"></code>

<API src="./index.tsx"></API>

API 间接从 ts 类型定义中主动生成

Demo 代码

在根目录创立 demo 文件夹,而后创立一个 Button 文件夹,创立一个 index.tsx 文件,

import React from 'react';
import {Button} from 'dumi-ui-site-template';

export default function App() {
  return (
    <>
      <div title="根底按钮">
        <Button>Default</Button>
        <Button active>Outline</Button>
        <Button danger>Danger</Button>
        <Button type="primary">Primary</Button>
        <Button type="primary" danger>
          Primary
        </Button>
      </div>

      <div title="块级按钮">
        <Button block>Block default</Button>
        <Button block type="primary">
          Block primary
        </Button>
        <Button block danger dashed>
          Block danger
        </Button>
      </div>
    </>
  );
}

这样一个根底的 Button 组件就构建好了,最初在 src/index.ts 文件中裸露进来

export {default as Button} from './Button';

预览成果

构建

  1. 构建站点文档

npm run docs:build 构建产物输入到docs-dist

  1. 构建组件开发脚手架

npm run build构建产物输入到es

系列文章

罕用 UI 组件库情谊举荐

  • ant design
  • Element
  • Naive UI

我是朽木白,一个酷爱分享的程序猿。如果感觉本文还不错,记得 三连 + 关注,说不定哪天就用得上!您的激励是我坚持下去的最大能源❤️。

正文完
 0