这是我参与「第五届青训营」伴学笔记创作活动的第 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 中,这样就可以实现子组件之间的间距了。暂时没想到更好的方法。