Каждый разработчик рано или поздно сталкивается с тем, что интерфейс начинает подтормаживать. Часто причина — неэффективная работа с DOM. В этой статье разберём, как заставить скрипты летать, а не ползать, и покажем конкретные приёмы с примерами кода.
Почему DOM — это медленно?
DOM (Document Object Model) — это представление HTML-документа в виде дерева объектов. Когда вы изменяете DOM, браузеру нужно пересчитать стили, перерисовать элементы и выполнить ещё кучу работы. Каждое обращение к DOM — как поход в магазин: можно сходить один раз и купить всё, а можно бегать за каждой мелочью. Чем больше таких «походов», тем медленнее.
Например, такой код:
for (let i = 0; i < 1000; i++) {
document.getElementById('list').innerHTML += `Item ${i} `;
}
Он будет работать очень медленно, потому что на каждой итерации происходит перерисовка всего списка. Вместо этого лучше собрать всё в строку и вставить один раз.
Правило первое: кэшируйте элементы
Если вы обращаетесь к одному и тому же элементу несколько раз, сохраните его в переменную. Поиск по DOM — дорогая операция.
// Плохо
for (let i = 0; i < 100; i++) {
document.querySelector('.my-element').style.color = 'red';
}
// Хорошо
const element = document.querySelector('.my-element');
for (let i = 0; i < 100; i++) {
element.style.color = 'red';
}
Правило второе: минимизируйте перерисовки
Браузер перерисовывает страницу после каждого изменения DOM. Если вы меняете стили или добавляете элементы в цикле, это вызывает множество перерисовок. Лучше сгруппировать изменения.
Самый простой способ — использовать DocumentFragment для добавления нескольких элементов:
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
document.getElementById('list').appendChild(fragment);
Или изменить стили через cssText:
// Плохо
element.style.color = 'red';
element.style.fontSize = '16px';
element.style.margin = '10px';
// Хорошо
element.style.cssText = 'color: red; font-size: 16px; margin: 10px;';
Правило третье: используйте делегирование событий
Если у вас много элементов, на которые нужно повесить обработчик, не вешайте его на каждый. Вместо этого повесьте один обработчик на родителя и используйте всплытие событий.
// Плохо: 100 обработчиков
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => btn.addEventListener('click', handleClick));
// Хорошо: 1 обработчик
document.getElementById('container').addEventListener('click', (event) => {
if (event.target.classList.contains('btn')) {
handleClick(event);
}
});
Это не только ускоряет работу, но и экономит память.
Правило четвёртое: избегайте layout thrashing
Layout thrashing (или «дёргание макета») происходит, когда вы чередуете чтение и запись в DOM. Браузер вынужден пересчитывать макет после каждой записи, чтобы вернуть актуальные данные при чтении.
Пример проблемного кода:
for (let i = 0; i < 10; i++) {
const width = element.offsetWidth; // чтение
element.style.width = width + 10 + 'px'; // запись
}
Лучше сначала выполнить все чтения, затем все записи:
const width = element.offsetWidth;
for (let i = 0; i < 10; i++) {
element.style.width = width + i * 10 + 'px';
}
Сравнение методов работы с DOM
В таблице ниже — основные методы и их производительность при массовых операциях.
| Метод | Когда использовать | Производительность |
|---|---|---|
| innerHTML | Массовая вставка HTML-строки | Высокая (но осторожно с XSS) |
| createElement + appendChild | Динамическое создание элементов | Средняя (много вызовов) |
| DocumentFragment | Добавление группы элементов | Высокая (одна перерисовка) |
| insertAdjacentHTML | Вставка HTML в определённое место | Высокая |
Что в итоге?
Оптимизация работы с DOM — это не магия, а набор простых правил. Кэшируйте элементы, группируйте изменения, используйте делегирование событий и избегайте layout thrashing. Эти приёмы помогут вашему коду работать быстрее и плавнее. И помните: лучше один раз вставить 1000 элементов через фрагмент, чем 1000 раз дёргать DOM по мелочи.
Попробуйте применить хотя бы одно правило в своём проекте — и вы заметите разницу.



