React中如何为列表元素监听keyPress事件?
解决列表元素键盘按键事件监听无效的问题
问题根源
onKeyPress已废弃且兼容性受限:该事件在现代浏览器中对方向键、回车键等常用按键不会触发,且MDN已标记为废弃,推荐用onKeyDown或onKeyUp替代。- 元素未获取焦点:即便设置了
tabIndex={0},键盘事件仅在元素获得焦点时才会触发,需通过Tab键切换到目标元素后再测试。
修复方案
1. 替换事件类型为onKeyDown
将原onKeyPress替换为onKeyDown,并在封装的MotionLI组件中同步支持该属性传递。
2. 完善无障碍键盘交互
对于role="button"的元素,需支持回车键和空格键触发点击逻辑,这是无障碍访问的标准要求。
修改后的代码示例
父组件部分
<MotionUL variants={dropUlAnimVariant}> {category.map((item, i, arr) => { const handleKeyDown = (e) => { // 监听回车和空格键,模拟点击行为 if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); // 阻止空格默认滚动行为 setCurrentCatItem(item); dispatch({ type: 'select', payload: i }); console.log(item); // 现在可正常输出 } // 如需监听更多按键,可在此扩展判断,比如方向键 // if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { ... } }; return ( <MotionLI key={i} className={`cursor-pointer list-none ${ i === state.selectIndex ? 'text-white' : 'text-gray-400' } hover:text-white ${ item === arr.slice(-1).join('') ? 'border-none' : 'border-b border-[#2d2d2d]' } py-2`} role="button" ariaPressed={i === state.selectIndex} tabIndex={0} onClick={() => { setCurrentCatItem(item); dispatch({ type: 'select', payload: i }); }} onKeyDown={handleKeyDown} // 替换为onKeyDown事件 > {item} </MotionLI> ); })} </MotionUL>
MotionLI.jsx组件部分
import React from 'react'; import { dropdownLiAnimVariant } from '../assets/constants'; import { motion } from 'framer-motion'; const MotionLI = ({ children, className, onClick, key, role, ariaPressed, tabIndex, onKeyDown, // 添加onKeyDown属性接收 }) => { return ( <motion.li className={className} onClick={onClick} variants={dropdownLiAnimVariant} whileTap={{ scale: 0.9 }} key={key} role={role} aria-pressed={ariaPressed} tabIndex={tabIndex} onKeyDown={onKeyDown} // 传递onKeyDown事件到底层元素 > {children} </motion.li> ); }; export default MotionLI;
验证步骤
测试时先通过Tab键将焦点切换到目标列表项,再按下回车/空格或其他按键,此时控制台应能正常输出内容。
内容的提问来源于stack exchange,提问作者Ishraque
相关产品推荐
相关产品推荐

