Custom Virtual List Implementation advanced productivity 92% Usefulness

Virtualisierte Listen mit Text-Messung optimieren

Wende Text-Messung an, um nur sichtbare Zeilen in großen Listen zu rendern, indem du vorab Zeilenhöhen berechnest statt live zu messen.

Originalvideo ansehen: He just crawled through hell to fix the browser…
3 Schritte
1

Alle Zeilenhöhen vorab berechnen

Berechne die Höhe jedes Text-Elements einmalig, bevor das Rendering beginnt

const messages = [/* 10.000 Nachrichten */];
const lineHeights = messages.map(msg => {
  const segments = pretext.prepare(msg.content, { font: '14px Arial' });
  return pretext.layout(segments, { width: 400 }).height;
});
Tipp: Speichere diese Höhen im State oder einer Map für schnelle Lookups
Warnung: Neu-Berechnung nur bei Font- oder Container-Änderungen
2

Scroll-Position zu sichtbarem Range mappen

Nutze Höhen, um zu berechnen, welche Zeilen sichtbar sind, basierend auf Scroll-Position

function calculateVisibleRange(lineHeights, scrollTop, viewportHeight) {
  let accumulatedHeight = 0;
  let startIndex = 0;
  let endIndex = 0;
  
  for (let i = 0; i < lineHeights.length; i++) {
    if (accumulatedHeight + lineHeights[i] > scrollTop) {
      startIndex = i;
      break;
    }
    accumulatedHeight += lineHeights[i];
  }
  
  accumulatedHeight = 0;
  for (let i = 0; i <= startIndex; i++) {
    accumulatedHeight += lineHeights[i];
  }
  
  while (accumulatedHeight < scrollTop + viewportHeight && endIndex < lineHeights.length) {
    accumulatedHeight += lineHeights[endIndex];
    endIndex++;
  }
  
  return { startIndex, endIndex };
}
Tipp: Verwende Binärsuche für O(log n) statt O(n) Komplexität
Warnung: Off-by-one Fehler sind häufig; teste mit Boundary-Cases
3

Nur sichtbare Items rendern

Rendere nur die Nachrichten zwischen startIndex und endIndex

const { startIndex, endIndex } = calculateVisibleRange(lineHeights, scrollTop, viewportHeight);
const visibleItems = messages.slice(startIndex, endIndex);

return (
  <div onScroll={(e) => setScrollTop(e.target.scrollTop)}>
    {visibleItems.map(item => <Message key={item.id} {...item} />)}
  </div>
);
Tipp: Rendere ein paar Extra-Items oberhalb/unterhalb für smootheres Scrollen
Warnung: ScrollListener sollte gedrosselt werden (requestAnimationFrame)
← Alle Playbooks anzeigen