You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:55:29