You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

实现搜索结果列表的键盘箭头导航功能

UI image

用户需求:搜索获取结果后,通过键盘箭头键上下移动列表项选中状态。

原代码片段:

<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状态管理选中索引,监听键盘事件处理导航逻辑,同时给选中项添加高亮样式:

  1. 添加状态:维护selectedIndex跟踪当前选中项的索引,初始值设为-1(未选中)
  2. 监听键盘事件:给输入框绑定onKeyDown事件,处理上下箭头及回车键逻辑
  3. 边界处理:箭头键循环切换选中项,避免索引越界
  4. 选中样式:渲染列表时根据selectedIndex给对应项添加高亮样式
  5. 可选优化:选中项变化时自动滚动到可视区域

修改后的完整代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:34:53