如何通过键盘事件实现搜索结果元素列表的箭头导航
实现搜索结果列表的键盘箭头导航功能

用户需求:搜索获取结果后,通过键盘箭头键上下移动列表项选中状态。
原代码片段:
<div> <input onChange={handleSearchChange}/> <div css={countryDataCss}> {countryList?.map((country) => ( <div key={country.countryCode}> <span css={countryCss}>{country.countryName}</span> <span css={countryDialCodeCss}> {country.countryDialNo} </span> </div> ))} </div> </div>
实现方案
通过React状态管理选中索引,监听键盘事件处理导航逻辑,同时给选中项添加高亮样式:
- 添加状态:维护
selectedIndex跟踪当前选中项的索引,初始值设为-1(未选中) - 监听键盘事件:给输入框绑定
onKeyDown事件,处理上下箭头及回车键逻辑 - 边界处理:箭头键循环切换选中项,避免索引越界
- 选中样式:渲染列表时根据
selectedIndex给对应项添加高亮样式 - 可选优化:选中项变化时自动滚动到可视区域
修改后的完整代码:
import { useState, useEffect } from 'react'; // 假设已有以下样式定义:countryDataCss、countryCss、countryDialCodeCss、countryItemBaseCss、selectedCountryCss const CountrySearch = () => { const [countryList, setCountryList] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [selectedIndex, setSelectedIndex] = useState(-1); const handleSearchChange = (e) => { const term = e.target.value; setSearchTerm(term); // 这里替换为你的搜索逻辑,比如过滤国家列表或请求接口 // 示例:const filtered = allCountries.filter(c => c.countryName.includes(term)); // setCountryList(filtered); setSelectedIndex(-1); // 搜索后重置选中状态 }; const handleKeyDown = (e) => { if (!countryList || countryList.length === 0) return; switch (e.key) { case 'ArrowDown': e.preventDefault(); setSelectedIndex(prev => prev >= countryList.length - 1 ? 0 : prev + 1 ); break; case 'ArrowUp': e.preventDefault(); setSelectedIndex(prev => prev <= 0 ? countryList.length - 1 : prev - 1 ); break; case 'Enter': e.preventDefault(); if (selectedIndex !== -1) { // 处理选中确认逻辑,比如选中当前国家 const selected = countryList[selectedIndex]; console.log('选中国家:', selected); } break; default: break; } }; // 自动滚动到选中项(可选) useEffect(() => { if (selectedIndex !== -1) { const item = document.getElementById(`country-item-${selectedIndex}`); item?.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }, [selectedIndex, countryList]); return ( <div> <input onChange={handleSearchChange} onKeyDown={handleKeyDown} value={searchTerm} placeholder="搜索国家" /> <div css={countryDataCss}> {countryList?.map((country, index) => ( <div key={country.countryCode} id={`country-item-${index}`} css={{ ...countryItemBaseCss, ...(selectedIndex === index ? selectedCountryCss : {}) }} > <span css={countryCss}>{country.countryName}</span> <span css={countryDialCodeCss}>{country.countryDialNo}</span> </div> ))} </div> </div> ); }; export default CountrySearch;
关键说明
- 按下
ArrowDown/ArrowUp时循环切换选中项,避免索引超出列表范围 - 回车键可触发选中项的确认操作,可根据需求自定义逻辑
- 选中项的高亮样式通过
selectedCountryCss实现,需提前定义对应样式(比如背景色变化) - 自动滚动逻辑确保长列表中选中项始终处于可视区域
内容的提问来源于stack exchange,提问作者Siva Sai
相关产品推荐
相关产品推荐

