使用react实现select
使用 React 实现 Select 组件
基础实现
创建一个基础的 Select 组件,包含下拉选项和状态管理:
import React, { useState } from 'react';
const Select = ({ options }) => {
const [selectedValue, setSelectedValue] = useState('');
const [isOpen, setIsOpen] = useState(false);
const handleSelect = (value) => {
setSelectedValue(value);
setIsOpen(false);
};
return (
<div className="select-container">
<div className="select-header" onClick={() => setIsOpen(!isOpen)}>
{selectedValue || 'Select an option'}
</div>
{isOpen && (
<div className="select-options">
{options.map((option) => (
<div
key={option.value}
className="select-option"
onClick={() => handleSelect(option.value)}
>
{option.label}
</div>
))}
</div>
)}
</div>
);
};
export default Select;
添加样式
为 Select 组件添加基本样式:
.select-container {
position: relative;
width: 200px;
}
.select-header {
padding: 8px;
border: 1px solid #ccc;
cursor: pointer;
}
.select-options {
position: absolute;
width: 100%;
border: 1px solid #ccc;
background: white;
z-index: 1;
}
.select-option {
padding: 8px;
cursor: pointer;
}
.select-option:hover {
background: #f0f0f0;
}
使用第三方库
如果需要更复杂的功能,可以使用第三方库如 react-select:
import React from 'react';
import Select from 'react-select';
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
const CustomSelect = () => {
return <Select options={options} />;
};
export default CustomSelect;
自定义功能
扩展基础 Select 组件,支持多选和搜索:
import React, { useState } from 'react';
const MultiSelect = ({ options }) => {
const [selectedValues, setSelectedValues] = useState([]);
const [isOpen, setIsOpen] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const filteredOptions = options.filter((option) =>
option.label.toLowerCase().includes(searchTerm.toLowerCase())
);
const handleSelect = (value) => {
setSelectedValues([...selectedValues, value]);
setSearchTerm('');
};
const removeSelected = (value) => {
setSelectedValues(selectedValues.filter((v) => v !== value));
};
return (
<div className="select-container">
<div className="select-header" onClick={() => setIsOpen(!isOpen)}>
{selectedValues.length === 0
? 'Select options'
: selectedValues.join(', ')}
</div>
{isOpen && (
<div className="select-options">
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
{filteredOptions.map((option) => (
<div
key={option.value}
className="select-option"
onClick={() => handleSelect(option.value)}
>
{option.label}
</div>
))}
</div>
)}
<div className="selected-tags">
{selectedValues.map((value) => (
<span key={value} className="tag">
{value}
<button onClick={() => removeSelected(value)}>×</button>
</span>
))}
</div>
</div>
);
};
export default MultiSelect;
无障碍支持
确保 Select 组件支持键盘导航和屏幕阅读器:
const AccessibleSelect = ({ options }) => {
const [selectedValue, setSelectedValue] = useState('');
const [isOpen, setIsOpen] = useState(false);
const [focusedIndex, setFocusedIndex] = useState(-1);
const handleKeyDown = (e) => {
if (e.key === 'ArrowDown') {
setFocusedIndex((prev) => Math.min(prev + 1, options.length - 1));
} else if (e.key === 'ArrowUp') {
setFocusedIndex((prev) => Math.max(prev - 1, 0));
} else if (e.key === 'Enter' && focusedIndex >= 0) {
handleSelect(options[focusedIndex].value);
} else if (e.key === 'Escape') {
setIsOpen(false);
}
};
const handleSelect = (value) => {
setSelectedValue(value);
setIsOpen(false);
setFocusedIndex(-1);
};
return (
<div className="select-container">
<div
className="select-header"
onClick={() => setIsOpen(!isOpen)}
onKeyDown={handleKeyDown}
tabIndex="0"
role="combobox"
aria-expanded={isOpen}
aria-haspopup="listbox"
>
{selectedValue || 'Select an option'}
</div>
{isOpen && (
<div
className="select-options"
role="listbox"
aria-activedescendant={focusedIndex >= 0 ? options[focusedIndex].value : undefined}
>
{options.map((option, index) => (
<div
key={option.value}
id={option.value}
className={`select-option ${focusedIndex === index ? 'focused' : ''}`}
onClick={() => handleSelect(option.value)}
role="option"
aria-selected={selectedValue === option.value}
>
{option.label}
</div>
))}
</div>
)}
</div>
);
};
这些方法提供了从基础到高级的 Select 组件实现方式,可以根据需求选择合适的方案。







