如何在React中实现分组自增tabindex的自定义hook
实现方案
方案1:全局连续索引Hook(完全匹配你要的调用效果)
该实现不受组件渲染次数影响,同组索引跨组件实例全局连续,仅当依赖的列表数据变更时才会重新生成索引:
import { useRef, useEffect } from 'react'; // 全局存储各组的基础偏移配置 const groupConfig = new Map(); // 自定义各组的基础偏移 export const setGroupBaseOffset = (groupName, offset) => { groupConfig.set(groupName, { base: offset, current: offset }); }; // 初始化默认组偏移,可按需扩展 setGroupBaseOffset('group1', 1000); setGroupBaseOffset('group2', 2000); // 自定义Hook export const useTabIndexGenerator = (deps = []) => { // 本地调用计数器,解决重渲染重复生成问题 const localCounters = useRef(new Map()); // 缓存已生成的索引,重渲染直接读取 const cachedIndexes = useRef(new Map()); // 依赖变更时重置本地状态,重新生成索引 useEffect(() => { localCounters.current.clear(); cachedIndexes.current.clear(); }, deps); const getNext = (groupName) => { if (!groupConfig.has(groupName)) return -1; const group = groupConfig.get(groupName); const localCount = localCounters.current.get(groupName) ?? 0; const cacheKey = `${groupName}_${localCount}`; // 已缓存的索引直接返回 if (cachedIndexes.current.has(cacheKey)) { localCounters.current.set(groupName, localCount + 1); return cachedIndexes.current.get(cacheKey); } // 生成新的全局连续索引 const newIndex = group.current + 1; group.current = newIndex; cachedIndexes.current.set(cacheKey, newIndex); localCounters.current.set(groupName, localCount + 1); return newIndex; }; return { getNext }; };
调用示例
// 传入列表作为依赖,仅当列表变化时才重新生成索引 const { getNext } = useTabIndexGenerator([attachmentsData?.data]); return ( {attachmentsData?.data?.map((attachment) => ( <FileName tabIndex={getNext('group1')} onClick={...}> {attachment.filename} </FileName> <AttachmentButtonContainer> <DownloadIcon tabIndex={getNext('group2')} ... /> </AttachmentButtonContainer> ))} );
方案2:极简工具函数封装(不需要跨实例全局连续时使用)
如果不需要跨多个组件实例的全局连续索引,只是想替换硬编码的偏移值,直接用工具函数即可,无需Hook:
const getGroupTabIndex = (groupName, index) => { const groupOffsets = { group1: 1000, group2: 2000, // 按需扩展其他组 }; return (groupOffsets[groupName] ?? 0) + index + 1; };
调用时直接传入组名和map遍历的index即可:
<FileName tabIndex={getGroupTabIndex('group1', tabIndex)} /> <DownloadIcon tabIndex={getGroupTabIndex('group2', tabIndex)} />
额外架构建议
- 优先避免使用正
tabindex:浏览器原生的Tab导航默认遵循DOM节点的排列顺序,只要DOM结构和预期的导航顺序一致,完全不需要手动设置正的tabindex。正tabindex会强制覆盖原生导航逻辑,反而容易引发可访问性问题,比如和浏览器默认控件、第三方组件的导航逻辑冲突。 - 如果确实需要调整导航顺序,优先调整DOM节点的排列顺序,而非修改
tabindex。 - 如果必须使用正
tabindex,建议将基础偏移值设得足够大(比如从10000开始),避免和页面内其他元素的tabindex冲突。
内容的提问来源于stack exchange,提问作者Roman Pushkin
相关产品推荐
相关产品推荐

