DOM: Document Object Model, дерево элементов

🌳 Что такое DOM и зачем он нужен?

DOM (Document Object Model) — это программное представление HTML-документа в виде дерева объектов. Браузер создаёт его автоматически при загрузке страницы, чтобы JavaScript мог взаимодействовать с элементами.

Без DOM мы не смогли бы: - Изменять контент страницы динамически - Реагировать на действия пользователя - Создавать интерактивные интерфейсы

<!-- Пример простого HTML -->
<div id="app">
  <h1>Привет, мир!</h1>
  <button>Нажми меня</button>
</div>

В DOM этот фрагмент превратится в иерархическую структуру:

document
└── html
    ├── head
     └── body
         └── div#app
            ├── h1
             └── button

Основные типы узлов DOM

DOM состоит из разных типов узлов. Вот самые важные:

Тип узла Пример Описание
Элемент <div>, <p> HTML-теги
Текст "Привет" Текстовое содержимое элементов
Комментарий <!-- комментарий --> HTML-комментарии
Документ document Корень дерева

🔍 Интересный факт: пробелы и переносы строк между тегами тоже становятся текстовыми узлами!


🔍 Как исследовать DOM в браузере

  1. Инструменты разработчика (F12) → Вкладка "Elements"
  2. Консольdocument для доступа к корню DOM
  3. JavaScript → методы для навигации по дереву
// Получаем элемент по id
const appDiv = document.getElementById('app');

// Получаем все элементы по тегу
const buttons = document.getElementsByTagName('button');

// Современный метод (аналог jQuery)
const h1 = document.querySelector('#app h1');

Навигация по DOM-дереву

У каждого DOM-элемента есть полезные свойства для перемещения:

const div = document.querySelector('div');

// Дочерние элементы
console.log(div.children); // Только элементы
console.log(div.childNodes); // Все узлы (включая текстовые)

// Родительский элемент
console.log(div.parentNode);

// Соседние элементы
console.log(div.previousElementSibling);
console.log(div.nextElementSibling);

💡 Совет: children возвращает только элементы, а childNodes — все узлы, включая текстовые и комментарии.


🌱 Создание и изменение элементов

DOM позволяет не только читать, но и изменять структуру страницы:

// Создаём новый элемент
const newParagraph = document.createElement('p');
newParagraph.textContent = 'Новый абзац!';

// Добавляем в DOM
document.body.appendChild(newParagraph);

// Изменяем стиль
newParagraph.style.color = 'blue';

// Добавляем класс
newParagraph.classList.add('highlight');

// Удаляем элемент через 3 секунды
setTimeout(() => {
  newParagraph.remove();
}, 3000);

🎯 Практический пример: интерактивный список

Давайте создадим список дел с возможностью добавления и удаления задач:

<div id="todo-app">
  <input type="text" id="task-input">
  <button id="add-btn">Добавить</button>
  <ul id="task-list"></ul>
</div>
const input = document.getElementById('task-input');
const addBtn = document.getElementById('add-btn');
const taskList = document.getElementById('task-list');

addBtn.addEventListener('click', () => {
  if (input.value.trim() === '') return;

  const li = document.createElement('li');
  li.textContent = input.value;

  const deleteBtn = document.createElement('button');
  deleteBtn.textContent = '❌';
  deleteBtn.addEventListener('click', () => li.remove());

  li.appendChild(deleteBtn);
  taskList.appendChild(li);

  input.value = '';
});

🚀 Производительность работы с DOM

Операции с DOM — одни из самых "дорогих" в JavaScript. Вот как их оптимизировать:

  1. Минимизируйте обращения к DOM — кэшируйте элементы в переменные
  2. Используйте DocumentFragment для массового добавления элементов
  3. Избегайте "перекомпоновки" (reflow) при частых изменениях стилей
// Неоптимально (много перекомпоновок)
for (let i = 0; i < 100; i++) {
  const div = document.createElement('div');
  document.body.appendChild(div);
}

// Оптимально (одна перекомпоновка)
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
  const div = document.createElement('div');
  fragment.appendChild(div);
}
document.body.appendChild(fragment);

🔥 Продвинутые техники

Shadow DOM

Позволяет создавать изолированные DOM-поддеревья (используется в веб-компонентах).

const host = document.getElementById('host');
const shadowRoot = host.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `<style>p { color: red; }</style><p>Только в Shadow DOM!</p>`;

MutationObserver

Следит за изменениями в DOM и выполняет колбэк при их обнаружении.

const observer = new MutationObserver(mutations => {
  console.log('DOM изменился!', mutations);
});

observer.observe(document.body, {
  childList: true,
  subtree: true,
  attributes: true
});
Скрыть рекламу навсегда

🎥 YouTube: программирование простым языком

Канал, где я спокойно и по шагам объясняю сложные темы — без заумных терминов и лишней теории.

Подходит, если раньше «не заходило», но хочется наконец понять.

▶️ Смотреть курсы на YouTube