Skip to content

Commit ddcadc6

Browse files
committed
[LES-5.8(9)/st-compl] improving-performance
Working with "DevTools/Performance", by template example. Worth noting: - createDocumentFragment() method. core: B-4 / WL-AL
1 parent f04c8fe commit ddcadc6

File tree

1 file changed

+65
-0
lines changed
  • core-courses/4-web-layout-advanced-level/5-web-page-rendering/5-8(9)-improving-performance

1 file changed

+65
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
// Пример шаблона, когда нужно обновить множество элементов на основе их текущего состояния.
4+
5+
const container = document.getElementById('container');
6+
const blocks = [];
7+
8+
// Создаем "виртуальный" контейнер в памяти. Вставка в него не вызывает перерисовку страницы.
9+
const fragment = document.createDocumentFragment();
10+
11+
for (let i = 0; i < 200; i++) {
12+
const div = document.createElement('div');
13+
div.className = 'box';
14+
15+
fragment.appendChild(div); // Добавляем элемент во фрагмент
16+
blocks.push(div); // Сохраняем ссылку на элемент в массив для быстрого доступа позже
17+
}
18+
19+
// ЕДИНСТВЕННОЕ обращение к DOM. Браузер отрисует все 200 элементов за один раз (1 Layout, 1 Paint).
20+
container.appendChild(fragment);
21+
22+
let rafCursor = null; // Храним ID анимации для отмены
23+
24+
function tick() {
25+
// Считываем размеры. Так как мы ничего не меняли в этом кадре ДО этого момента,
26+
// браузер берет данные из кэша и не запускает Reflow.
27+
const measures = blocks.map((block) => {
28+
return {
29+
el: block,
30+
newHeight: block.offsetHeight + 1, // Чтение метрики
31+
};
32+
});
33+
34+
// Применяем изменения. Layout инвалидируется (становится "грязным").
35+
// Но так как чтение уже закончено, браузер выполнит пересчет только ОДИН раз в конце выполнения скрипта, перед отрисовкой кадра.
36+
measures.forEach((data) => {
37+
data.el.style.height = `${data.newHeight}px`; // Запись стиля
38+
});
39+
40+
// Планируем следующий кадр
41+
rafCursor = requestAnimationFrame(tick);
42+
}
43+
44+
function startAnimation() {
45+
if (!rafCursor) {
46+
tick();
47+
}
48+
}
49+
50+
function pauseAnimation() {
51+
if (rafCursor) {
52+
cancelAnimationFrame(rafCursor);
53+
rafCursor = null;
54+
55+
// Сброс высоты (также лучше делать пакетно, но здесь для краткости так)
56+
blocks.forEach((block) => {
57+
block.style.height = '20px';
58+
});
59+
}
60+
}
61+
62+
document.getElementById('start').addEventListener('click', startAnimation);
63+
document.getElementById('pause').addEventListener('click', pauseAnimation);
64+
65+
// !! Хотя этот метод убирает Layout Thrashing, изменение height все равно вызывает Reflow (пусть и один). Для идеальной анимации 60FPS, если логика позволяет, лучше использовать transform: scaleY(), так как это задействует только Composite (GPU).

0 commit comments

Comments
 (0)