如何实现带内嵌文本编辑框的单选按钮组?
带内嵌输入框的单选按钮组实现方案
基础HTML/CSS/JS实现
适合无框架场景,核心是将单选按钮与输入框绑定为同一交互单元,通过CSS规整布局,JS处理状态逻辑:
结构代码
<div class="size-filter-group"> <label class="radio-option"> <input type="radio" name="sizeFilter" value="no-limit" checked> <span>无大小限制</span> </label> <label class="radio-option"> <input type="radio" name="sizeFilter" value="max-size"> <span>最大大小:</span> <input type="number" class="size-input" placeholder="KB" disabled> </label> <label class="radio-option"> <input type="radio" name="sizeFilter" value="min-size"> <span>最小大小:</span> <input type="number" class="size-input" placeholder="KB" disabled> </label> <label class="radio-option"> <input type="radio" name="sizeFilter" value="size-range"> <span>大小范围:</span> <input type="number" class="size-input" placeholder="最小KB" disabled> <span> - </span> <input type="number" class="size-input" placeholder="最大KB" disabled> </label> </div>
样式调整(CSS)
.size-filter-group { display: flex; flex-direction: column; gap: 12px; padding: 16px; } .radio-option { display: flex; align-items: center; gap: 8px; cursor: pointer; } .size-input { width: 80px; padding: 4px 8px; border: 1px solid #ddd; border-radius: 4px; } .size-input:disabled { background-color: #f5f5f5; cursor: not-allowed; }
交互逻辑(JS)
const radioInputs = document.querySelectorAll('input[name="sizeFilter"]'); const sizeInputs = document.querySelectorAll('.size-input'); radioInputs.forEach(radio => { radio.addEventListener('change', () => { // 先禁用所有输入框 sizeInputs.forEach(input => input.disabled = true); // 根据选中项启用对应输入框 const selectedValue = radio.value; if (selectedValue === 'max-size' || selectedValue === 'min-size') { radio.parentElement.querySelector('.size-input').disabled = false; } else if (selectedValue === 'size-range') { radio.parentElement.querySelectorAll('.size-input').forEach(input => input.disabled = false); } }); }); // 提交时的参数处理示例 function handleSubmit() { const selectedRadio = document.querySelector('input[name="sizeFilter"]:checked'); let filterParams = {}; switch(selectedRadio.value) { case 'no-limit': filterParams.size = null; break; case 'max-size': const maxSize = selectedRadio.parentElement.querySelector('.size-input').value; filterParams.maxSize = maxSize ? parseInt(maxSize) : null; break; case 'min-size': const minSize = selectedRadio.parentElement.querySelector('.size-input').value; filterParams.minSize = minSize ? parseInt(minSize) : null; break; case 'size-range': const [rangeMin, rangeMax] = selectedRadio.parentElement.querySelectorAll('.size-input'); filterParams.sizeRange = { min: rangeMin.value ? parseInt(rangeMin.value) : null, max: rangeMax.value ? parseInt(rangeMax.value) : null }; break; } // 将参数传入后台查询逻辑 console.log('筛选参数:', filterParams); }
React组件实现
基于React的状态管理,逻辑更简洁可控:
import { useState } from 'react'; const SizeFilter = () => { const [selectedOption, setSelectedOption] = useState('no-limit'); const [maxSize, setMaxSize] = useState(''); const [minSize, setMinSize] = useState(''); const [rangeMin, setRangeMin] = useState(''); const [rangeMax, setRangeMax] = useState(''); const handleRadioChange = (e) => { setSelectedOption(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); let filterParams = {}; switch(selectedOption) { case 'no-limit': filterParams.size = null; break; case 'max-size': filterParams.maxSize = maxSize ? parseInt(maxSize) : null; break; case 'min-size': filterParams.minSize = minSize ? parseInt(minSize) : null; break; case 'size-range': filterParams.sizeRange = { min: rangeMin ? parseInt(rangeMin) : null, max: rangeMax ? parseInt(rangeMax) : null }; break; } // 提交到后台查询 console.log('筛选参数:', filterParams); }; return ( <form onSubmit={handleSubmit} className="size-filter-group"> <label className="radio-option"> <input type="radio" name="sizeFilter" value="no-limit" checked={selectedOption === 'no-limit'} onChange={handleRadioChange} /> <span>无大小限制</span> </label> <label className="radio-option"> <input type="radio" name="sizeFilter" value="max-size" checked={selectedOption === 'max-size'} onChange={handleRadioChange} /> <span>最大大小:</span> <input type="number" className="size-input" placeholder="KB" disabled={selectedOption !== 'max-size'} value={maxSize} onChange={(e) => setMaxSize(e.target.value)} /> </label> <label className="radio-option"> <input type="radio" name="sizeFilter" value="min-size" checked={selectedOption === 'min-size'} onChange={handleRadioChange} /> <span>最小大小:</span> <input type="number" className="size-input" placeholder="KB" disabled={selectedOption !== 'min-size'} value={minSize} onChange={(e) => setMinSize(e.target.value)} /> </label> <label className="radio-option"> <input type="radio" name="sizeFilter" value="size-range" checked={selectedOption === 'size-range'} onChange={handleRadioChange} /> <span>大小范围:</span> <input type="number" className="size-input" placeholder="最小KB" disabled={selectedOption !== 'size-range'} value={rangeMin} onChange={(e) => setRangeMin(e.target.value)} /> <span> - </span> <input type="number" className="size-input" placeholder="最大KB" disabled={selectedOption !== 'size-range'} value={rangeMax} onChange={(e) => setRangeMax(e.target.value)} /> </label> <button type="submit">应用筛选</button> </form> ); }; export default SizeFilter;
关键注意事项
- 输入校验:添加数字格式、非空校验(选中对应选项时),比如范围选项需确保最小值不大于最大值。
- 可访问性:用label包裹单选与输入框,添加合适的aria属性,符合WCAG标准。
- 样式适配:可根据项目UI规范调整布局(比如横向排列选项)和样式细节。
内容的提问来源于stack exchange,提问作者Syzygy
相关产品推荐
相关产品推荐

