您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
选择器组件,文档如下:
组件封装代码如下:
import React, { FC, useMemo, createRef, useEffect, useState, useCallback, memo } from 'react';
import { DownOutlined, LoadingOutlined, CloseOutlined } from '@ant-design/icons';
import style from './index.module.less';
interface Options {
label: String | number;
value: String | number;
disabled?: Boolean;
}
interface SelectProps {
/**
* @description 选择器数据
* @default []
*/
option: Array<Options>;
/**
* @description 宽度
* @default 80px
*/
width?: Number;
/**
* @description 提示
* @default false
*/
placeholder?: String;
/**
* @description 禁用状态
* @default false
*/
disabled?: Boolean;
/**
* @description 加载状态
* @default false
*/
loading?: Boolean;
/**
* @description 可输入状态
* @default false
*/
showSearch?: Boolean;
/**
* @description 可输入状态下清除
* @default false
*/
clearable?: Boolean;
/**
* @description 选择后的回调
* @default {}
*/
handleSelectCallback?: Function;
/**
* @description 输入后的回调
* @default {}
*/
handleTextChange?: Function;
}
const Select: FC<SelectProps> = (props) => {
const {
option,
width,
placeholder,
disabled,
loading,
showSearch,
clearable,
handleSelectCallback,
handleTextChange,
} = props;
const [selected, setSelected] = useState<string | number | any>('');
const optionRef = createRef() as any;
useEffect(() => {
optionRef.current.style.height = `0px`;
}, []);
const ownsWidth = useMemo(() => {
//传参宽度
if (width) {
return {
width: `${width}px`,
};
}
return {};
}, [width]);
const disabledStyle = useMemo(() => {
//禁用状态
if (disabled) {
return {
cursor: 'not-allowed',
background: 'rgb(238, 238, 238)',
};
}
}, [disabled]);
const toggleOptions = (e: any) => {
//切换下拉
e.stopPropagation();
if (disabled) return;
if (optionRef.current.style.height === '0px') {
if (showSearch) {
optionRef.current.style.height = `${inputFilterOtpions.length * 100}%`;
} else {
optionRef.current.style.height = `${option.length * 100}%`;
}
} else {
optionRef.current.style.height = '0px';
}
};
const changeOptions = (v: Options, e: any) => {
//选择选项
e.stopPropagation();
if (v.disabled) return;
optionRef.current.style.height = '0px';
setSelected(v.label);
if (handleSelectCallback) {
handleSelectCallback(v.value);
}
};
const inputFilterOtpions = useMemo(() => {
//输入状态options过滤
return option.filter((item) => {
return (item.label as string).includes(selected);
});
}, [option, selected]);
const handleInputChange = useCallback(
(e: any) => {
//输入后的回调
setSelected(e.target.value);
optionRef.current.style.height =
option.filter((item) => {
return (item.label as string).includes(e.target.value);
}).length *
100 +
'%';
if (handleTextChange) {
handleTextChange(e.target.value);
}
},
[selected],
);
return showSearch ? (
<>
<div className={style.select} style={{ ...ownsWidth, ...disabledStyle }}>
<div className={style.selected}>
<input
type="text"
className={style.selected}
value={selected}
placeholder={placeholder as string}
onClick={toggleOptions}
onChange={(e) => handleInputChange(e)}
/>
{clearable ? (
<CloseOutlined onClick={() => setSelected('')} />
) : (
<DownOutlined onClick={toggleOptions} />
)}
</div>
<div className={style.selectOptions} style={ownsWidth} ref={optionRef}>
{inputFilterOtpions.map((s) => {
return (
<div
key={s.label as any}
className={style.option}
style={
s.disabled ? { cursor: 'not-allowed', background: 'rgb(238, 238, 238)' } : {}
}
onClick={(e) => changeOptions(s as Options, e)}
>
{s.label}
</div>
);
})}
</div>
</div>
</>
) : (
<div className={style.select} style={{ ...ownsWidth, ...disabledStyle }}>
<div className={style.selected} onClick={toggleOptions}>
{selected ? (
<div className={style.size}>{selected}</div>
) : (
(placeholder && <div className={style.placeholder}>{placeholder}</div>) || <div />
)}
{loading ? <LoadingOutlined /> : <DownOutlined />}
</div>
<div className={style.selectOptions} style={ownsWidth} ref={optionRef}>
{option.map((s) => {
return (
<div
key={s.label as any}
className={style.option}
style={s.disabled ? { cursor: 'not-allowed', background: 'rgb(238, 238, 238)' } : {}}
onClick={(e) => changeOptions(s as Options, e)}
>
{s.label}
</div>
);
})}
</div>
</div>
);
};
export default memo(Select);
- Concis组件库线上链接:react-view-ui.com:92
- github:github.com/fengxinhhh/…
- npm:www.npmjs.com/package/con…