基于react+ts的简单Space组件 | 青训营笔记

174 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 8 天,今天准备着手制作一个简单的基于react+ts的Space组件。自己之前没有接触过有关组件库的编写,文章中若出现错误欢迎指正。

Space 组件

需求分析

一个简单的 Space 组件需要的哪些功能? 作为一个布局组件,它需要能够控制子组件的排列方式,排列方向,子组件之间的间隔距离,还有是否能够换行等功能。还有能够控制子组件高度等等功能,但是今天暂且先实现一个简单的版本尝试一下。

接口定义

export enum SpaceingSize {
  Small = "small",
  Medium = "medium",
  Large = "large",
}

export enum Direction {
  Horizontal = "horizontal",
  Vertical = "vertical",
}

export enum Side {
  Left = "left",
  Right = "right",
  Center = "center",
}

interface BaseSpaceProps {
  size?: SpaceingSize;
  wrap?: boolean;
  side?: Side;
  direction?: Direction;
}

我们为组件定义了一些基本参数,size 表示子组件之间的间距,wrap 表示是否换行,side 表示子组件在父组件中的位置,direction 表示子组件的排列方向。这些都是可选属性。

有关 eslint 与本地代码格式化插件 Prettier 的冲突

在初次使用 eslint 时出现的报错发现和 Prettier 有关,两者对于格式化代码的要求有冲突,根据报错,在我的环境中,冲突的地方有以下三点:

  • 使用单双引号的冲突
  • 行末分号的冲突
  • 末行逗号添加的冲突

我选择修改 Prettier 的配置来解决,在根目录创建文件.prettierrc,加入下列配置:

{
  "singleQuote": true,
  "semi": false,
  "trailingComma": "none"
}

冲突解决。

组件实现

const Space: React.FC<SpaceProps> = (props) => {
  const { size, wrap, side, direction, children, ...restProps } = props;
  const classes = classNames("Space", {
    [`Space-${direction}`]: direction,
    "Space-break": direction === Direction.Horizontal && wrap,
    [`Space-vertical-${side}`]: direction === Direction.Vertical && side,
    [`Space-horizontal-${side}`]: direction === Direction.Horizontal && side,
  });
  const itemClasses = classNames("Space_item", {
    [`Space-${size}`]: size,
  });
  return (
    <div className={classes} {...restProps}>
      {React.Children.map(children, (child) => (
        <div className={itemClasses}>{child}</div>
      ))}
    </div>
  );
};

Space.defaultProps = {
  size: SpaceingSize.Medium,
  direction: Direction.Horizontal,
  wrap: true,
  side: Side.Left,
};

在代码中,我们使用了 classnames 库来动态生成类名,这样可以减少代码量,使代码更加简洁。根据不同的参数,我们传入相应的 className,这样就可以实现不同的样式效果。

在组件中,我们使用了 React.Children.map 方法来遍历子组件,然后将子组件包裹在一个 div 中,这样就可以实现子组件之间的间距了。暂时没想到更好的方法。

下次更新继续完善这个组件,并且进行组件测试。