Вивчай

Маніпуляція DOM

JavaScript маніпуляція DOM — скульптор вирізає форму з мармурового блокуJavaScript маніпуляція DOM — скульптор вирізає форму з мармурового блоку

У минулому уроці ми навчилися знаходити елементи на сторінці та змінювати їхній текст, стилі та атрибути. Але що, якщо потрібно створити новий елемент, якого ще немає в HTML? Або видалити існуючий? Сьогодні розберемо, як JavaScript може повністю керувати структурою сторінки.


createElement — створення елементів

Метод document.createElement(tag) створює новий HTML-елемент у пам'яті. Він ще не з'являється на сторінці — лише існує в JavaScript:

const paragraph = document.createElement("p");

// Елемент створено, але він поки "в повітрі" — не на сторінці
console.log(paragraph); // <p></p>

Після створення можна налаштувати елемент — додати текст, класи, атрибути:

const card = document.createElement("div");
card.textContent = "Привіт, я нова картка!";
card.classList.add("card", "card--primary");
card.setAttribute("data-id", "42");

// Елемент готовий, але досі не на сторінці
Порада

Спочатку повністю налаштуй елемент (текст, класи, атрибути), а потім додавай на сторінку. Це ефективніше, бо браузер перемальовує сторінку тільки один раз.


Додавання елементів на сторінку

appendChild — додати в кінець

const list = document.querySelector(".todo-list");

const item = document.createElement("li");
item.textContent = "Вивчити DOM";

list.appendChild(item); // додає <li> в кінець списку

append та prepend

Сучасніші методи з більшими можливостями:

const container = document.querySelector(".container");

const title = document.createElement("h2");
title.textContent = "Заголовок";

const text = document.createElement("p");
text.textContent = "Опис";

// append — додає в кінець (може кілька елементів + текст)
container.append(title, text, "Просто текст");

// prepend — додає на початок
const notice = document.createElement("div");
notice.textContent = "Увага!";
container.prepend(notice);

before та after — поруч з елементом

const secondItem = document.querySelector(".item:nth-child(2)");

const newItem = document.createElement("div");
newItem.textContent = "Новий елемент";

secondItem.before(newItem);  // вставити ПЕРЕД другим елементом
secondItem.after(newItem);   // вставити ПІСЛЯ другого елемента

Порівняння методів додавання

МетодКуди додаєПриймає
parent.appendChild(el)В кінець parentТільки один елемент
parent.append(el, ...)В кінець parentЕлементи + текст
parent.prepend(el, ...)На початок parentЕлементи + текст
el.before(el2, ...)Перед elЕлементи + текст
el.after(el2, ...)Після elЕлементи + текст

Видалення елементів

remove() — видалити елемент

const notification = document.querySelector(".notification");
notification.remove(); // елемент зникає зі сторінки

removeChild() — видалити дочірній

Старіший метод, іноді потрібний:

const list = document.querySelector("ul");
const firstItem = list.querySelector("li");

list.removeChild(firstItem); // видаляє перший <li> зі списку
Інфо

remove() з'явився у сучасних браузерах. Старий підхід — parent.removeChild(child). У сучасному коді використовуй remove().


cloneNode — клонування елементів

Іноді простіше скопіювати існуючий елемент, ніж створювати новий з нуля:

const original = document.querySelector(".card");

// Поверхнева копія — тільки сам елемент, без дочірніх
const shallowCopy = original.cloneNode(false);

// Глибока копія — елемент з усім вмістом
const deepCopy = original.cloneNode(true);

document.querySelector(".container").append(deepCopy);
Увага

cloneNode(true) копіює HTML-структуру, але не копіює обробники подій, додані через addEventListener. Якщо потрібні обробники — додавай їх після клонування.


insertAdjacentHTML — вставка HTML-рядка

Коли потрібно вставити шматок HTML як рядок:

const container = document.querySelector(".container");

container.insertAdjacentHTML("beforeend", "<p class='note'>Нова нотатка</p>");

Чотири позиції вставки:

<!-- beforebegin -->
<div class="container">
  <!-- afterbegin -->
  <p>Існуючий контент</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
const box = document.querySelector(".box");

box.insertAdjacentHTML("beforebegin", "<h2>Перед box</h2>");
box.insertAdjacentHTML("afterbegin", "<p>Перший дочірній</p>");
box.insertAdjacentHTML("beforeend", "<p>Останній дочірній</p>");
box.insertAdjacentHTML("afterend", "<footer>Після box</footer>");
Увага

insertAdjacentHTML має ту саму проблему, що й innerHTML — не вставляй сюди дані від користувача без перевірки (ризик XSS-атаки). Для тексту безпечніше використовувати createElement + textContent.


DocumentFragment — batch-операції

Коли потрібно додати багато елементів, кожен append змушує браузер перемальовувати сторінку. DocumentFragment — це невидимий контейнер, який дозволяє зібрати всі елементи разом, а потім додати їх одним рухом:

const list = document.querySelector(".list");
const fruits = ["Яблуко", "Банан", "Апельсин", "Манго", "Ківі"];

const fragment = document.createDocumentFragment();

fruits.forEach((fruit) => {
  const li = document.createElement("li");
  li.textContent = fruit;
  li.classList.add("list-item");
  fragment.appendChild(li); // додаємо у fragment, а не на сторінку
});

list.appendChild(fragment); // одна операція — одне перемалювання
Порада

Для невеликої кількості елементів (5-10) різниця непомітна. Але для сотень елементів DocumentFragment значно швидший. Це хороша звичка для будь-якої кількості.


Практика: динамічний список

Побудуємо список користувачів з масиву даних:

<div id="app">
  <h2>Список користувачів</h2>
  <ul class="user-list"></ul>
</div>
const users = [
  { name: "Олексій", role: "Розробник" },
  { name: "Марія", role: "Дизайнер" },
  { name: "Андрій", role: "Менеджер" },
  { name: "Катерина", role: "Тестувальник" },
];

const userList = document.querySelector(".user-list");
const fragment = document.createDocumentFragment();

users.forEach((user) => {
  const li = document.createElement("li");
  li.classList.add("user-item");

  const nameSpan = document.createElement("span");
  nameSpan.textContent = user.name;
  nameSpan.classList.add("user-name");

  const roleSpan = document.createElement("span");
  roleSpan.textContent = user.role;
  roleSpan.classList.add("user-role");

  li.append(nameSpan, " — ", roleSpan);
  fragment.appendChild(li);
});

userList.appendChild(fragment);

Підсумок

  • createElement(tag) — створює елемент у пам'яті
  • append / prepend — додають в кінець / на початок батьківського елемента
  • before / after — вставляють поруч з елементом
  • remove() — видаляє елемент зі сторінки
  • cloneNode(true) — глибока копія елемента з вмістом
  • insertAdjacentHTML — вставка HTML-рядка у чотири позиції
  • DocumentFragment — збирає елементи перед вставкою (одне перемалювання)

Що далі?

У наступному уроці вивчимо події — як JavaScript реагує на дії користувача: кліки, наведення миші та інше.

Інфо

Корисні посилання: