map函数遍历数组时如何访问当前索引的下一个数组元素
问题原因
Array.map的回调函数第一个参数是当前遍历到的元素值,不是原数组的引用,所以你对thing做操作时,本质是在操作当前位置的ID值本身:
- 写
thing[1]时,是对ID对应的字符串/数字按下标取值,拿到的是当前值的第二个字符 - 写
thing+1时,会触发JS的隐式类型转换:如果thing是字符串就拼接字符"1",如果是数字就做数值+1运算,完全不会访问到数组的相邻元素
另外你当前的渲染逻辑没有包裹<tr>行标签,且每遇到一个偶数索引就输出2个单元格,和你需要的每行4个单元格(2组ID+匹配串)的结构不匹配,就算拿到下一个元素也会出现表格结构错乱。
解决方案
推荐方案:先预处理数据再渲染
20000条数据的预处理性能消耗极低,逻辑和渲染分离后代码更易维护,也不需要在渲染时做大量奇偶判断:
// 第一步:先把原始扁平数组整理成ID-匹配串的配对数组 const pairs = [] for (let i = 0; i < objInnerValues.length; i += 2) { pairs.push({ id: objInnerValues[i], str: objInnerValues[i+1] }) } // 第二步:把配对数组按每行2组的结构,整理成表格行数据 const tableRows = [] for (let i = 0; i < pairs.length; i += 2) { tableRows.push({ leftId: pairs[i]?.id, leftStr: pairs[i]?.str, rightId: pairs[i+1]?.id, rightStr: pairs[i+1]?.str }) }
上面的写法默认每行按顺序放2组数据,如果需要和示例完全一致的双栏交错排版,只需要调整第二步的切片逻辑,将配对数组对半拆分后按行对齐即可,渲染层代码不需要改动。同时这个写法兼容数据总数不是4的倍数的场景,最后一行缺数据时不会渲染undefined。
之后直接遍历行数据渲染即可,不需要在渲染阶段做索引计算:
<tbody> {tableRows.map((row, idx) => ( <tr key={row.leftId || idx}> <td>{row.leftId}</td> <td>{row.leftStr}</td> <td>{row.rightId}</td> <td>{row.rightStr}</td> </tr> ))} </tbody>
临时方案:直接在map中访问原数组
map回调的第三个参数就是当前遍历的原数组本身,你可以通过原数组[当前索引 + 偏移量]拿到相邻元素,但这种写法需要自己处理行标签包裹和边界判断,不推荐:
<tbody> {objInnerValues.map((thing, Index, arr) => { // 每4个元素渲染一行,只在索引为0、4、8...的时候生成行标签 if (Index % 4 !== 0) return null return ( <tr key={Index}> <SuperTH>{arr[Index]}</SuperTH> <SuperTD NoHoverTD>{arr[Index+1]}</SuperTD> <SuperTH>{arr[Index+2]}</SuperTH> <SuperTD NoHoverTD>{arr[Index+3]}</SuperTD> </tr> ) })} </tbody>
注意事项
- 不要在渲染分支里返回
console.log,控制台输出没有实际DOM返回值,会生成多余的空注释节点拖慢渲染性能,不需要渲染的分支直接返回null即可 - 渲染列表时一定要给行标签加唯一
key,如果你的ID是全局唯一的,用ID当key比索引作为key的渲染性能更好 - 表格结构必须严格遵循
table > thead/tbody > tr > td/th的嵌套规则,不要直接在tbody下输出th/td,否则会出现浏览器自动修正DOM结构导致的样式错乱
内容的提问来源于stack exchange,提问作者Basil Nagle
相关产品推荐
相关产品推荐

