DOM (Document Object Model) — это объектная модель документа, которая представляет HTML как дерево объектов:
// Основные операции с DOM
document.getElementById('myId');
document.querySelector('.myClass');
element.innerHTML = 'Новый контент';
element.addEventListener('click', handler);DOM — это как мост между HTML-разметкой и JavaScript! Браузер превращает статичный HTML в живое дерево объектов, с которыми можно взаимодействовать. 🌉
DOM представляет документ как дерево:
<!DOCTYPE html>
<html>
<head>
<title>Заголовок</title>
</head>
<body>
<h1>Привет</h1>
<p>Текст параграфа</p>
</body>
</html>// Структура в DOM
document
├── html
├── head
│ └── title
│ └── "Заголовок"
└── body
├── h1
│ └── "Привет"
└── p
└── "Текст параграфа"// Основные типы узлов
Node.ELEMENT_NODE = 1; // <div>, <p>
Node.TEXT_NODE = 3; // Текстовый контент
Node.COMMENT_NODE = 8; // <!-- комментарий -->
Node.DOCUMENT_NODE = 9; // document
// Проверка типа
if (node.nodeType === Node.ELEMENT_NODE) {
console.log('Это элемент');
}// По ID
const element = document.getElementById('myId');
// По классу
const elements = document.getElementsByClassName('myClass');
// По тегу
const paragraphs = document.getElementsByTagName('p');
// CSS селекторы
const first = document.querySelector('.class');
const all = document.querySelectorAll('div > p');// Родительские элементы
element.parentNode;
element.parentElement;
// Дочерние элементы
element.childNodes; // Все узлы
element.children; // Только элементы
element.firstChild;
element.lastChild;
// Соседние элементы
element.nextSibling;
element.previousSibling;
element.nextElementSibling;// Текстовое содержимое
element.textContent = 'Новый текст';
element.innerText = 'Видимый текст';
// HTML содержимое
element.innerHTML = '<strong>Жирный текст</strong>';
// Атрибуты
element.setAttribute('class', 'newClass');
element.getAttribute('id');
element.removeAttribute('style');// Прямое изменение стилей
element.style.color = 'red';
element.style.backgroundColor = 'blue';
element.style.fontSize = '16px';
// CSS классы
element.classList.add('active');
element.classList.remove('hidden');
element.classList.toggle('visible');
element.classList.contains('selected');// Создание нового элемента
const div = document.createElement('div');
div.textContent = 'Новый блок';
div.className = 'my-class';
// Добавление в DOM
document.body.appendChild(div);
parent.insertBefore(div, referenceNode);
parent.insertAdjacentHTML('beforeend', '<p>HTML</p>');// Удаление элемента
element.remove();
parent.removeChild(element);
// Замена элемента
parent.replaceChild(newElement, oldElement);
// Клонирование
const clone = element.cloneNode(true); // true = глубокое// Современный способ
element.addEventListener('click', function(event) {
console.log('Клик!', event.target);
});
// Множественные обработчики
element.addEventListener('click', handler1);
element.addEventListener('click', handler2);
// Удаление обработчика
element.removeEventListener('click', handler1);// Фаза погружения (capture)
element.addEventListener('click', handler, true);
// Остановка всплытия
function handler(event) {
event.stopPropagation();
event.preventDefault();
}
// Делегирование событий
document.addEventListener('click', function(event) {
if (event.target.matches('.button')) {
console.log('Кнопка нажата');
}
});// Плохо: множественные обращения
for (let i = 0; i < 1000; i++) {
document.body.appendChild(createElement());
}
// Хорошо: batch операции
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
fragment.appendChild(createElement());
}
document.body.appendChild(fragment);// Плохо: повторные поиски
document.getElementById('myId').style.color = 'red';
document.getElementById('myId').style.fontSize = '16px';
// Хорошо: кеширование
const element = document.getElementById('myId');
element.style.color = 'red';
element.style.fontSize = '16px';// Отслеживание видимости элементов
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('Элемент виден');
}
});
});
observer.observe(element);// Отслеживание изменений DOM
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log('DOM изменился:', mutation.type);
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});// Медленные операции
element.innerHTML = newContent; // Перерисовка
element.style.color = 'red'; // Reflow/Repaint// Виртуальное представление
const vdom = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', children: 'Заголовок' },
{ type: 'p', children: 'Текст' }
]
};// Группировка изменений
element.style.cssText = 'color: red; font-size: 16px;';
// Использование классов вместо прямых стилей
element.className = 'active highlighted';// Вместо множества обработчиков
document.addEventListener('click', function(event) {
const target = event.target;
if (target.matches('.button')) {
handleButton(target);
} else if (target.matches('.link')) {
handleLink(target);
}
});// Создание элементов по требованию
function createExpensiveElement() {
if (!this.cachedElement) {
this.cachedElement = document.createElement('div');
// Настройка элемента
}
return this.cachedElement;
}❌ Неправильно:
// Поиск в цикле
for (let i = 0; i < items.length; i++) {
document.getElementById('list').appendChild(items[i]);
}
// Забыли про память
element.addEventListener('click', handler);
// Не удалили обработчик при удалении элемента✅ Правильно:
// Кеширование и batch операции
const list = document.getElementById('list');
const fragment = document.createDocumentFragment();
items.forEach(item => fragment.appendChild(item));
list.appendChild(fragment);
// Очистка обработчиков
element.removeEventListener('click', handler);DOM — основа интерактивности веб-страниц:
Понимание DOM — ключ к эффективной веб-разработке! 🚀