在Mat-table列表中使用输入框,为何30条及以上记录时UI无响应?
启用虚拟滚动
Material Table默认渲染所有行数据,30+条带输入的行会生成大量DOM节点,直接拖慢UI。可以结合虚拟滚动组件(如react-window、react-virtualized),只渲染当前视口内的行,滚动时动态切换渲染范围,大幅减少DOM数量。如果Material Table有内置虚拟滚动选项,直接开启即可;没有的话,把表格的行容器替换成虚拟滚动容器,控制仅加载可见区域的数据。优化输入组件的重渲染
把每行的输入字段抽成独立组件,用React.memo包裹,确保只有当输入值、回调函数或行ID变化时才重渲染,避免父组件更新时所有输入组件跟着刷新。示例代码:
const TableInput = React.memo(({ value, onChange, rowId }) => { return <input value={value} onChange={(e) => onChange(rowId, e.target.value)} />; });
批量处理状态更新
如果每条输入都触发一次全局表格数据更新,会导致频繁的状态变更和重渲染。可以用防抖函数延迟更新状态,合并短时间内的多次输入操作;或者用ref临时存储输入值,等用户完成输入(比如输入框失焦、点击保存按钮)时再批量更新全局状态,减少重渲染次数。缓存复杂计算结果
检查表格渲染时是否有重复执行的复杂计算(比如行内的格式化、数据转换),用useMemo缓存这些计算结果,只有当依赖数据变化时才重新计算,避免每次渲染都消耗资源。示例:
const processedTableData = useMemo(() => { return rawData.map(row => ({ ...row, formattedValue: formatRowValue(row) // 耗时的格式化函数 })); }, [rawData]);
关闭不必要的表格特性
如果开启了不需要的表格功能(如实时排序、自动列宽调整、实时筛选),直接关闭。比如不需要输入时自动排序,就把排序触发改成手动按钮触发,避免输入操作触发额外的表格计算和重渲染。拆分组件缩小渲染范围
把表格拆分为表头、表体、行组件等独立模块,每个模块只处理自身的状态和props。这样某一行的输入变化只会触发该行组件的重渲染,而不是整个表格组件刷新。
内容的提问来源于stack exchange,提问作者Shahid Khan

