DOM дерево
DOM (Document Object Model) — древовидное представление HTML-документа в виде объектов, доступных для манипуляции через JavaScript.
Зачем нужно
DOM — мост между HTML и JavaScript. Через DOM можно читать содержимое страницы, менять его, добавлять элементы, реагировать на действия пользователя.
Где используется
- Динамическое изменение страницы
- Обработка форм и ввода
- Анимации и визуальные эффекты
- SPA-фреймворки (React, Vue работают с виртуальным DOM)
Предпосылки
Введение в JavaScript, Объекты
Структура DOM
<!DOCTYPE html>
<html>
<head>
<title>Моя страница</title>
</head>
<body>
<h1>Заголовок</h1>
<p>Текст</p>
</body>
</html>
document
└── html (Element)
├── head (Element)
│ └── title (Element)
│ └── "Моя страница" (Text)
└── body (Element)
├── h1 (Element)
│ └── "Заголовок" (Text)
└── p (Element)
└── "Текст" (Text)
Типы узлов (nodeType)
const el = document.querySelector('h1');
// Основные типы
Node.ELEMENT_NODE; // 1 — HTML-элемент
Node.TEXT_NODE; // 3 — текстовый узел
Node.COMMENT_NODE; // 8 — комментарий
Node.DOCUMENT_NODE; // 9 — document
console.log(el.nodeType); // 1
console.log(el.nodeName); // "H1"
console.log(el.tagName); // "H1" (только для элементов)
// Текстовый узел
const textNode = el.firstChild;
console.log(textNode.nodeType); // 3
console.log(textNode.nodeValue); // "Заголовок"
document — корень DOM
// Ключевые свойства document
document.documentElement; // <html>
document.head; // <head>
document.body; // <body>
document.title; // заголовок страницы
document.URL; // текущий URL
document.domain; // домен
document.readyState; // "loading" | "interactive" | "complete"
// Коллекции
document.forms; // все <form>
document.images; // все <img>
document.links; // все <a> с href
document.scripts; // все <script>
Свойства узлов
const div = document.querySelector('div');
// Содержимое
div.innerHTML; // HTML-содержимое (строка)
div.outerHTML; // Включая сам элемент
div.textContent; // Только текст (без тегов)
div.innerText; // Видимый текст (учитывает CSS display)
// Атрибуты
div.id; // значение id
div.className; // строка классов
div.classList; // DOMTokenList (add, remove, toggle, contains)
div.getAttribute('data-id'); // любой атрибут
div.setAttribute('data-id', '5');
div.removeAttribute('data-id');
div.hasAttribute('data-id');
// dataset — data-* атрибуты
// <div data-user-id="42" data-role="admin">
div.dataset.userId; // "42"
div.dataset.role; // "admin"
// Стили
div.style.color = 'red';
div.style.backgroundColor = 'blue'; // camelCase!
div.style.cssText = 'color: red; background: blue'; // строка
getComputedStyle(div).fontSize; // реальное значение из CSS
Частые ошибки
1. innerHTML vs textContent
const div = document.querySelector('div');
// innerHTML парсит HTML — уязвимость XSS!
div.innerHTML = userInput; // Опасно! Пользователь может вставить <script>
// textContent — безопасно, экранирует HTML
div.textContent = userInput; // Безопасно
2. Скрипт до загрузки DOM
// В <head> без defer — элементы ещё не существуют
const el = document.querySelector('#app'); // null!
// Решения:
// 1. defer атрибут: <script defer src="app.js">
// 2. Скрипт перед </body>
// 3. DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
const el = document.querySelector('#app'); // OK
});
Практика
- Выведи в консоль nodeType и nodeName для 5 разных узлов
- Измени textContent и innerHTML элемента и сравни результат
- Прочитай и установи data-атрибуты через dataset