最新的项目需求中 UI 设计了一个按钮样式的多选框,选中之后在按钮右上角有一个白色对勾,表示选中状态;之后在 Antd 内查看组件文档,发现没有这个状态的复选框,无奈,只能自己写了;
耗时半小时,简单写了一下,能满足需求,不过如果想作为一个比较完善的公共组件,有一些地方需要去细化一下,考虑不同情况,比如 options
数据格式的校验、组件样式的传递、以及代码优化等等;
下面是代码,首先是组件本体
// 按钮状态的多选框
import React, { useState } from 'react';
import { Space } from 'antd';
const CheckButtonGroup = (props) => {
const [value, setValue] = useState({});
const { options } = props;
const handleChange = (index, selected) => {
const newValue = value;
if (selected) {
newValue[index] = options[index].value;
} else {
newValue[index] = '';
}
setValue(newValue);
const propsValue: string[] = [];
Object.keys(newValue).forEach((key) => {
if (newValue[key]) {
propsValue.push(newValue[key]);
}
});
props.onChange?.(propsValue);
};
return (
<div>
<Space size={20} wrap>
{options.map((op, index) => (
<CheckButton key={op.value} onClick={handleChange} index={index}>
{op.label}
</CheckButton>
))}
</Space>
</div>
);
};
这个组件用到了另一个组件,此组件是按钮的本体
import React, { useState } from 'react';
import classNames from 'classnames';
import styles from './index.module.less';
const CheckButton = (props) => {
const [isSelected, setSelected] = useState(false);
const handleClick = () => {
props.onClick(props.index, !isSelected);
setSelected(!isSelected);
};
return (
<span
className={classNames(styles.default, {
[styles.selected]: isSelected,
})}
onClick={handleClick}
>
<span>{props.children}</span>
</span>
);
};
组件样式
.default {
display: inline-block;
padding: 10px 24px;
border: 1px solid #C8C8C8;
color: #212223;
border-radius: 4px;
}
.selected {
border: 1px solid #017EFA;
color: #017EFA;
position: relative;
&:before {
content: "";
position: absolute;
right: 0;
top: 0;
border: 10px solid #017EFA;
border-bottom-color: transparent;
border-left-color: transparent;
}
&:after {
content: "";
width: 3px;
height: 6px;
position: absolute;
right: 3px;
top: 0;
border: 1px solid #fff;
border-top-color: transparent;
border-left-color: transparent;
transform: rotate(45deg);
}
}
组件使用
<CheckButtonGroup
options={[
{ label: '测试多选', value: 'time' },
{ label: '按钮样式', value: 'position' },
{ label: '多选框', value: 'name' },
{ label: '看效果', value: 'type' },
{ label: '还可以', value: 'level' },
{ label: '改样式', value: 'source' },
]}
onChange={(value) => {
console.log(value);
}}
/>
组件效果
写的比较粗糙,若有错误可指出,改不改的那就看情况了;