前言
因为做的是大屏的项目,样式要和大屏的颜色相同,所以就自己写了一个简易的select组件,还参考了ant design的select组件实现了下拉菜单在展开时点击其他地方自动收起下拉菜单。 ps:当然没有ant那么的复杂,主要使用了contains方法。
contains
这是IE的方法,其他浏览器也有支持,唯一不支持这个方法的是firefox。如果A元素包含B元素,则返回true,否则false。。
tsx
import { useState, useEffect, useRef } from 'react';
interface selectProps {
option: any;
defaultValue: string;
selectStyle?: object;
onSelect?: Function;
}
const Select = (props: selectProps) => {
const { option } = props;
const { defaultValue, selectStyle, onSelect } = props;
let [checked, setChecked] = useState(false);
let [value, setValue] = useState(defaultValue);
let selectRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const selectCheck = (e: any) => {
if (!(selectRef.current as HTMLDivElement).contains(e.target)) {
console.log('select元素不包含点击元素', selectRef.current, e.target);
setChecked(false);
}
};
document.addEventListener('click', selectCheck);
return () => document.removeEventListener('click', selectCheck);
}, []);
// 点击显示下拉菜单
const checkedItem = (e: any) => {
console.log('checkedItem', checked);
// e.stopPropagation();
if (checked) {
setChecked(false);
} else {
setChecked(true);
}
};
// 点击option触发
const checkedOption = (e: any) => {
setValue(e.target.innerText);
onSelect && onSelect(e.target.innerText);
setChecked(false);
};
return (
<>
<div
className={style.cSelect}
style={selectStyle}
ref={selectRef}
onClick={checkedItem}
>
<div className={style.select}>
<div className={style.selectItem}>
<div className={style.defaultValue}>
<div className={style.value}>{value}</div>
{!checked ? (
<div className={style.downLined}></div>
) : (
<div className={style.upLined}></div>
)}
</div>
{checked
? option.map((item: string, index: number) => {
return (
<div
className={style.option}
key={index}
onClick={checkedOption}
>
{item}
</div>
);
})
: null}
</div>
</div>
</div>
</>
);
};
export default Select;
less
position: relative;
width: 180px;
height: 100%;
.select {
position: absolute;
z-index: 999;
width: 100%;
border-radius: 10px;
background: #051f52;
.selectItem {
width: 100%;
font-size: 14px;
padding: 0 7px;
cursor: pointer;
background: linear-gradient(
180deg,
rgba(17, 130, 229, 0.4),
rgba(16, 129, 228, 0) 49%,
rgba(17, 130, 228, 0.4)
);
border: 1px solid #1079d8;
border-radius: 10px;
.value {
color: #fff;
}
.defaultValue {
width: 100%;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
.downLined {
width: 0;
height: 0;
border-right: 5px solid transparent;
border-left: 5px solid transparent;
border-top: 8px solid #1084e8;
margin-left: 10px;
}
.upLined {
width: 0;
height: 0;
border-right: 5px solid transparent;
border-left: 5px solid transparent;
border-bottom: 8px solid #1084e8;
margin-left: 10px;
}
}
.option {
width: 100%;
height: 32px;
padding: 0 10px;
border-top: 0.5px solid #106ec8;
line-height: 32px;
}
}
.noOption {
display: none;
}
}
}