点击ScrollToTop回到顶部按钮后如何设置焦点到其他组件的元素
实现方案
步骤1:改造ScrollToTop组件,支持滚动完成回调
首先修复原组件滚动事件重复绑定的问题,同时新增滚动完成后的回调触发逻辑,等待平滑滚动结束后执行自定义操作:
import { useState, useEffect, useCallback } from 'react'; interface ScrollToTopProps { onScrollComplete?: () => void; } const ScrollToTop = ({ onScrollComplete }: ScrollToTopProps) => { const [showScrollButton, setShowScrollButton] = useState<boolean>(false); const checkScrollToTop = useCallback(() => { setShowScrollButton(window.pageYOffset > 400); }, []); const scrollToTop = () => { window.scrollTo({ top: 0, behavior: 'smooth' }); // 监听滚动结束事件,触发回调后自动解绑 const handleScrollEnd = () => { onScrollComplete?.(); window.removeEventListener('scrollend', handleScrollEnd); }; window.addEventListener('scrollend', handleScrollEnd); }; // 滚动事件绑定放到useEffect中,避免重复绑定、内存泄漏 useEffect(() => { window.addEventListener('scroll', checkScrollToTop); return () => window.removeEventListener('scroll', checkScrollToTop); }, [checkScrollToTop]); if (!showScrollButton) return null; return ( <button type='button' onClick={scrollToTop} aria-label="回到顶部" > 回到顶部 </button> ); } export default ScrollToTop;
如果需要兼容不支持scrollend事件的旧浏览器,可以把滚动结束监听替换为定时触发,时长和滚动动画时长保持一致即可,示例:
setTimeout(() => onScrollComplete?.(), 500)
步骤2:改造List组件,暴露内部目标元素的ref
使用forwardRef将父组件传入的ref绑定到你需要聚焦的内部元素上,同时给非交互元素添加tabIndex=-1属性支持JS聚焦:
import { forwardRef } from 'react'; interface ListProps { collections: any[]; // 替换为你实际的collections类型 } const List = forwardRef<HTMLDivElement, ListProps>(({ collections }, ref) => { return ( <div className="list-container"> {/* 将ref绑定到需要聚焦的目标元素,此处以列表标题为例,可替换为你实际的目标元素 */} <h2 ref={ref} tabIndex={-1}>列表标题</h2> {collections.map(item => ( <div key={item.id} className="list-item">{item.content}</div> ))} </div> ); }); List.displayName = 'List'; export default List;
步骤3:父组件关联逻辑
在父组件中创建ref关联List内部的目标元素,给ScrollToTop传入滚动完成后聚焦目标元素的回调即可:
import { useRef } from 'react'; import List from './List'; import ScrollToTop from './ScrollToTop'; const YourPage = () => { const targetFocusRef = useRef<HTMLDivElement>(null); const collections = []; // 你的实际数据 const handleScrollComplete = () => { targetFocusRef.current?.focus(); }; return ( <> <div> <List collections={collections} ref={targetFocusRef} /> </div> <ScrollToTop onScrollComplete={handleScrollComplete} /> </> ); }; export default YourPage;
注意事项
- 非交互元素(div、h1~h6等)必须添加
tabIndex=-1属性才能通过JS调用focus方法生效,且该属性不会让元素被Tab键遍历选中,符合 accessibility 规范 - 如果你的项目是JS版本,删除所有类型定义即可直接运行
内容的提问来源于stack exchange,提问作者user14649590
相关产品推荐
相关产品推荐

