React 17+react-router-dom5.2:如何检测页面路由是否由键盘触发?
解决方案
1. 封装带状态的导航链接组件
改造侧边栏的导航链接,通过监听点击/键盘事件,在跳转时携带「是否通过键盘进入」的状态:
import { Link, useHistory } from 'react-router-dom'; function SidebarNavLink({ to, children }) { const history = useHistory(); const handleNavigation = (isKeyboard) => { // 存入localStorage处理页面刷新场景,同时用history.push传递状态 localStorage.setItem('enteredByKeyboard', isKeyboard.toString()); history.push({ pathname: to, state: { enteredByKeyboard: isKeyboard } }); }; return ( <Link to={to} onClick={(e) => { e.preventDefault(); // 阻止Link默认跳转逻辑 handleNavigation(false); }} onKeyDown={(e) => { // 处理Enter和空格两种键盘触发跳转的情况 if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleNavigation(true); } }} > {children} </Link> ); }
2. 在目标组件中读取状态并设置tabIndex
在TestComponent中,通过useLocation获取路由携带的状态,同时处理直接输入URL/页面刷新的场景:
import { useLocation } from 'react-router-dom'; import { useState, useEffect } from 'react'; import TestHeader from './TestHeader'; function TestComponent() { const location = useLocation(); const [enteredByKeyboard, setEnteredByKeyboard] = useState(false); useEffect(() => { let fromKeyboard = location.state?.enteredByKeyboard; // 若路由无状态,说明是直接输入URL或刷新页面,读取localStorage临时值 if (fromKeyboard === undefined) { const storedValue = localStorage.getItem('enteredByKeyboard'); fromKeyboard = storedValue === 'true'; localStorage.removeItem('enteredByKeyboard'); // 用完清除,避免干扰其他页面 } setEnteredByKeyboard(fromKeyboard); }, [location]); return ( <div className="page-container"> <TestHeader title="" tabIndex={enteredByKeyboard ? 1 : 0} /> {/* 页面其他内容 */} </div> ); }
逻辑说明
- 鼠标点击导航链接时,标记
enteredByKeyboard: false并传递给目标页面 - 键盘聚焦链接后按Enter/空格跳转时,标记
enteredByKeyboard: true - 直接输入URL或刷新页面时,路由无携带状态,默认设为
false - 用localStorage临时存储状态,解决页面刷新后路由state丢失的问题
内容的提问来源于stack exchange,提问作者Pikk
相关产品推荐
相关产品推荐

