Der Browser möchte die Stilberechnung und die Layout-Arbeiten bündeln. Leistungsprobleme treten auf, wenn Anwendungs-Code diesen Plan ständig unterbricht, indem er abwechselnd DOM-Schreiboperationen und Layout-Leseoperationen in engen Schleifen ausführt.
Dieses Muster wird normalerweise als Layout-Thrashing bezeichnet.
Das Fehler-Muster
Das ist die kostspielige Form:
for (const item of items) {
item.style.width = "200px";
const rect = item.getBoundingClientRect();
item.style.height = `${rect.width}px`;
}
Jeder Aufruf von getBoundingClientRect() kann den Browser zwingen, ausstehende Layout-Arbeiten abzuschließen, bevor er antworten kann. Wenn dies während des Scrollens, Resizings oder einer Animation geschieht, wird die Benutzeroberfläche schnell ruckelig.
Besseres Muster
Zuerst die Leseoperationen bündeln. Zweitens die Schreiboperationen bündeln:
const widths = items.map((item) => item.getBoundingClientRect().width);
items.forEach((item, index) => {
item.style.width = "200px";
item.style.height = `${widths[index]}px`;
});
Das ist nicht der einzige mögliche Fix, aber es zeigt die zugrunde liegende Regel: Vermeide es, den Browser wiederholt zur Neuberechnung des Layouts innerhalb von rahmensensitiven Code zu zwingen.
Wann es tatsächlich wichtig ist
Man merkt es normalerweise in:
- Scroll-Handlern
- Animationsschleifen
- Drag-and-Drop-Interaktionen
- großen Listen mit direkter DOM-Manipulation
Der Browser ist schnell, wenn du ihm die Arbeit bündeln lässt. Es wird kostspielig, wenn du ihn zwingst, geometrische Fragen sofort nach jedem Schreibvorgang zu beantworten.
Wenn der Code während einer Animation oder Interaktion ausgeführt werden muss, ist requestAnimationFrame oft der richtige Ort, um gebündelte DOM-Arbeiten zu planen, sodass Lese- und Schreiboperationen in einem vorhersehbareren Rahmen durchgeführt werden.
Weitere Informationen