Skip to content

遅延ロード実装

非常に大きなデータセット(例:数百万件)を扱う場合、すべてのデータを一度にレンダリングするとパフォーマンスの問題が発生します。StkTableには仮想スクロールの最適化機能が内置されていますが、すべてのデータを一度にメモリにロードすると、依然として大量のリソースを消費します。

テーブルのscrollイベントをリッスンすることで、現在の表示領域のstartIndexendIndexを取得でき、必要に応じてデータを読み込む遅延ロードソリューションを実現できます。

実装アプローチ

  1. 大きなプレースホルダー配列を作成し、dataSourceに渡す
  2. scrollイベントをリッスンしてstartIndexendIndexを取得
  3. スクロール位置に基づいてロードが必要なデータページを計算
  4. APIからオンデマンドでデータを取得し、対応する位置に填充
loading

実装詳細

コアロジック

typescript
// 假设总数据量为 100000 条,每页 100 条
const totalCount = 100000;
const pageSize = 100;

// 创建占位数组
const tableDataRef = useRef<Array<Record<string, any>>>(
  Array(totalCount).fill(null).map((_, i) => ({ id: i + 1, __placeholder: true }))
);

// 监听滚动事件
function onScroll(ev: Event, data: { startIndex: number; endIndex: number }) {
  const { startIndex, endIndex } = data;
  
  // 计算需要加载的页码范围
  const startPage = Math.floor(startIndex / pageSize);
  const endPage = Math.floor(endIndex / pageSize);
  
  // 加载范围内的数据页
  for (let page = startPage; page <= endPage; page++) {
    loadDataPage(page);
  }
}

// 加载指定页的数据
async function loadDataPage(page: number) {
  // 检查是否已加载
  const startIndex = page * pageSize;
  if (!tableDataRef.current[startIndex]?.__placeholder) return;
  
  // 从接口获取数据
  const response = await fetchData(page, pageSize);
  
  // 填充到对应位置
  response.forEach((item, index) => {
    tableDataRef.current[startIndex + index] = item;
  });
}

境界ケースの処理

スクロール位置がちょうど2ページの間にがある場合(例:startIndex=95, endIndex=105)、両方のページを同時にロードする必要があります(ページ0とページ1)。これにより、表示領域内のデータが完全に確実に表示されます。

注意事項

  1. 仮想スクロールがスクロール高さを正しく計算できるよう、プレースホルダー配列を事前に割り当てる必要があります
  2. ロード済みのデータは適切にキャッシュし、重複リクエストを回避してください
  3. ユーザーエクスペリエンスを向上させるため、ローディング状態のインジケーターを追加することを検討してください

MITライセンスの下で公開されています