Изменение DOM
Создание элементов
const div = document.createElement('div');
const text = document.createTextNode('Привет');
const fragment = document.createDocumentFragment();
Добавление
parent.appendChild(el); // в конец
parent.append(el, 'текст'); // в конец, несколько
parent.prepend(el); // в начало
parent.before(el); // до
parent.after(el); // после
parent.replaceChild(newEl, oldEl);
append и prepend принимают строки и узлы:
list.append('текст', anotherElement);
Удаление
parent.removeChild(el);
parent.remove(); // сам себя
Перемещение
newParent.appendChild(existingEl); // переместит, а не скопирует
Клонирование
const clone = el.cloneNode(); // без детей
const deep = el.cloneNode(true); // с детьми
Текст
el.textContent = 'новый текст'; // безопасно
el.innerText = 'новый текст'; // учитывает стили
el.innerHTML = '<b>HTML</b>'; // парсит HTML
Разница:
textContent— быстрее, не парсит HTMLinnerText— учитывает CSS (скрытые элементы)innerHTML— парсит HTML, опасен с пользовательскими данными
XSS через innerHTML
const userInput = '<img src=x onerror="alert(1)">';
el.innerHTML = userInput; // выполнит скрипт
Используй textContent или санитизацию.
Атрибуты
el.setAttribute('href', '/new');
el.getAttribute('href');
el.removeAttribute('href');
el.id = 'new-id';
el.className = 'new-class';
el.href = '/new'; // для ссылок
Стили
el.style.color = 'red';
el.style.fontSize = '16px';
el.style.cssText = 'color: red; font-size: 16px';
el.style.removeProperty('color');
Через классы:
el.classList.add('active');
el.classList.remove('active');
el.classList.toggle('active');
Создание структуры
const card = document.createElement('div');
card.className = 'card';
const title = document.createElement('h3');
title.textContent = 'Заголовок';
const body = document.createElement('p');
body.textContent = 'Текст';
card.append(title, body);
document.body.append(card);
Шаблоны
<template id="card-template">
<div class="card">
<h3></h3>
<p></p>
</div>
</template>
const template = document.getElementById('card-template');
const clone = template.content.cloneNode(true);
clone.querySelector('h3').textContent = 'Заголовок';
clone.querySelector('p').textContent = 'Текст';
document.body.append(clone);
DocumentFragment
Контейнер без родителя. Вставляется одним действием:
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Элемент ${i}`;
fragment.appendChild(li);
}
list.appendChild(fragment); // одно обращение к DOM
Быстрее, чем 100 отдельных вставок.
Производительность
Каждое изменение DOM вызывает reflow и repaint. Минимизируй:
// Плохо: 100 reflow
for (let i = 0; i < 100; i++) {
list.append(createItem(i));
}
// Хорошо: 1 reflow
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
fragment.append(createItem(i));
}
list.append(fragment);
Итоги
- Создание через
createElement append,prepend,before,afterremoveдля удаленияtextContentбезопаснееinnerHTMLtemplateдля шаблоновDocumentFragmentдля массовых вставок