遍历apiData生成千个动态输入框致页面卡顿,求优化方案
优化上千个输入框渲染卡顿的方案
一次性渲染上千个输入框会触发大量DOM操作与浏览器重绘重排,直接导致主线程阻塞、页面卡顿。以下是针对性的优化方案:
1. 虚拟滚动(最推荐)
虚拟滚动仅渲染当前可视区域内的元素,将DOM数量从1000级压缩到几十级,从根源解决卡顿问题。如果你的CustomTable本身支持虚拟滚动(如TanStack Table的rowVirtualization配置),直接开启即可;若不支持,可通过第三方库实现:
import { FixedSizeList as List } from 'react-window'; import React from 'react'; // 封装虚拟滚动表格组件 function VirtualizedTable({ columns, data }) { const Row = ({ index, style }) => { return ( <div style={style} className="table-row"> {columns.map(col => ( <div key={col.id} className="table-cell"> {col.accessorKey} </div> ))} </div> ); }; return ( <div> {/* 表头 */} <div className="table-header"> {columns.map(col => ( <div key={col.id} className="table-header-cell"> {col.header} </div> ))} </div> {/* 虚拟滚动列表 */} <List height={500} // 可视区域高度,可自定义 itemCount={data.length} itemSize={40} // 每行固定高度,可自定义 width="100%" > {Row} </List> </div> ); } // 修改你的组件 export default function DynamicsInputs({ apiData }) { const columns = apiData.map((option) => ({ header: option.Title, accessorKey: <input type='number' key={option.ID} />, id: option.ID })); const data = Array(apiData.length).fill({}); // 匹配输入框行数的空数据 return ( <div> <VirtualizedTable columns={columns} data={data} /> </div> ); }
2. 分批延迟渲染
将输入框分成多批,利用浏览器空闲时间逐步渲染,避免一次性阻塞主线程:
import React, { useState, useEffect } from 'react'; export default function DynamicsInputs({ apiData }) { const [renderedCount, setRenderedCount] = useState(50); // 初始渲染50个 const batchSize = 50; // 每批渲染数量,可调整 useEffect(() => { const timer = setInterval(() => { setRenderedCount(prev => { const newCount = prev + batchSize; if (newCount >= apiData.length) { clearInterval(timer); return apiData.length; } return newCount; }); }, 100); // 每100ms渲染一批,可调整间隔 return () => clearInterval(timer); }, [apiData.length]); const columns = apiData.slice(0, renderedCount).map((option) => ({ header: option.Title, accessorKey: <input type='number' key={option.ID} />, id: option.ID })); return ( <div> <CustomTable column={columns} data={data} /> {renderedCount < apiData.length && <div>加载中...</div>} </div> ); }
3. 优化输入组件的渲染性能
确保输入框不会触发不必要的重渲染,用React.memo包裹纯输入组件:
// 封装纯输入组件 const MemoizedInput = React.memo(() => { return <input type='number' />; }); // 修改你的columns生成逻辑 const columns = React.useMemo(() => { return apiData.map((option) => ({ header: option.Title, accessorKey: <MemoizedInput key={option.ID} />, id: option.ID })); }, [apiData]); // 仅当apiData变化时重新生成columns
4. 调整accessorKey的渲染方式
你的代码中直接在accessorKey返回<input>元素,若CustomTable每次渲染都会重新解析该元素,可能引发额外重渲染。建议改为渲染函数,让表格按需创建元素:
const columns = apiData.map((option) => ({ header: option.Title, accessorKey: () => <input type='number' key={option.ID} />, // 改为函数形式 id: option.ID })); // 同时修改CustomTable内部,调用该函数渲染: // {col.accessorKey()}
内容的提问来源于stack exchange,提问作者user22378454
相关产品推荐
相关产品推荐

