js 实现combox
实现基本结构
使用HTML创建ComboBox的基本结构,包含一个输入框和一个下拉列表。下拉列表默认隐藏,通过JavaScript控制显示与隐藏。
<div class="combo-box">
<input type="text" class="combo-input" placeholder="Select an option">
<ul class="combo-options">
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
</div>
样式设计
通过CSS为ComboBox添加基础样式,包括输入框边框、下拉列表的定位和悬停效果。
.combo-box {
position: relative;
width: 200px;
}
.combo-input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
}
.combo-options {
display: none;
position: absolute;
width: 100%;
border: 1px solid #ccc;
list-style: none;
padding: 0;
margin: 0;
background: white;
}
.combo-options li {
padding: 8px;
cursor: pointer;
}
.combo-options li:hover {
background: #f0f0f0;
}
交互逻辑
使用JavaScript实现下拉列表的显示/隐藏功能,以及选项选择后更新输入框内容。
document.addEventListener('DOMContentLoaded', function() {
const input = document.querySelector('.combo-input');
const options = document.querySelector('.combo-options');
input.addEventListener('focus', () => {
options.style.display = 'block';
});
input.addEventListener('blur', () => {
setTimeout(() => options.style.display = 'none', 200);
});
options.querySelectorAll('li').forEach(li => {
li.addEventListener('click', () => {
input.value = li.textContent;
options.style.display = 'none';
});
});
});
动态数据加载
通过异步请求动态加载下拉选项数据,适用于数据量较大的场景。
function loadOptions(url) {
fetch(url)
.then(response => response.json())
.then(data => {
const options = document.querySelector('.combo-options');
options.innerHTML = data.map(item => `<li>${item.name}</li>`).join('');
});
}
loadOptions('https://api.example.com/options');
键盘导航支持
增强用户体验,允许通过键盘上下键选择选项并回车确认。
input.addEventListener('keydown', (e) => {
const items = options.querySelectorAll('li');
let currentIndex = Array.from(items).findIndex(li => li.classList.contains('highlighted'));
if (e.key === 'ArrowDown') {
e.preventDefault();
currentIndex = (currentIndex + 1) % items.length;
updateHighlight(items, currentIndex);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
currentIndex = (currentIndex - 1 + items.length) % items.length;
updateHighlight(items, currentIndex);
} else if (e.key === 'Enter' && currentIndex >= 0) {
input.value = items[currentIndex].textContent;
options.style.display = 'none';
}
});
function updateHighlight(items, index) {
items.forEach(li => li.classList.remove('highlighted'));
items[index].classList.add('highlighted');
}
性能优化
对于大型数据集,采用虚拟滚动技术减少DOM渲染压力。

function renderVisibleOptions(startIndex, endIndex) {
const visibleData = allData.slice(startIndex, endIndex);
options.innerHTML = visibleData.map(item => `<li>${item.name}</li>`).join('');
}





