Основы DOM для начинающих: манипуляция и структура в JavaScript
#Веб-разработка #Основы JavaScript #Работа с DOMДля кого эта статья:
- начинающие разработчики, интересующиеся веб-разработкой
- студенты и учащиеся на курсах программирования
- практикующие программисты, желающие улучшить свои навыки в работе с JavaScript и DOM
Многие начинающие разработчики сталкиваются с загадочным термином DOM и не понимают, почему знание этого аспекта критически важно для JavaScript-разработки. Между простым написанием скрипта и созданием динамичного интерактивного приложения лежит пропасть — и мост через неё именно DOM. Взаимодействие с элементами веб-страницы, изменение их содержимого и стилей, создание новых элементов "на лету" — все эти навыки делают из начинающего кодера настоящего JavaScript-мастера. Раскроем эти таинства веб-разработки, которые превращают статичную страницу в живое, реагирующее на действия пользователя приложение. 🚀
Что такое DOM и зачем он нужен в JavaScript
DOM (Document Object Model) — это программный интерфейс, представляющий HTML-документ в виде древовидной структуры объектов, с которыми можно взаимодействовать через JavaScript. По сути, DOM — это мост между вашим HTML-кодом и JavaScript-скриптами.
Когда браузер загружает веб-страницу, он создаёт DOM — модель документа, которая хранится в памяти. JavaScript может манипулировать этой моделью, что позволяет динамически изменять содержимое страницы без её перезагрузки.
Антон Лисицын, ведущий frontend-разработчик
Помню свой первый серьезный проект — админ-панель для интернет-магазина. Заказчик хотел, чтобы при добавлении нового товара форма оставалась на месте, а товар сразу появлялся в списке без перезагрузки страницы. Я провел несколько дней, пытаясь реализовать это с помощью обычных форм и submit, но получалось топорно — страница мигала при обновлении.
Когда я наконец понял DOM и научился создавать элементы динамически через JavaScript, это стало откровением! Я написал функцию, которая получала данные из формы, отправляла их на сервер через AJAX и добавляла новую строку в таблицу товаров прямо на странице. Заказчик был в восторге от плавности работы интерфейса, а я — от того, как элегантно решил задачу с помощью DOM-манипуляций.
Зачем вообще нужен DOM? Без него JavaScript не смог бы взаимодействовать с HTML-страницей. DOM предоставляет JavaScript доступ к элементам страницы и позволяет:
- Изменять содержимое элементов (тексты, атрибуты)
- Модифицировать стили и классы элементов
- Реагировать на действия пользователя (клики, ввод в поля)
- Создавать новые элементы и удалять существующие
- Анимировать элементы страницы
Сравним страницы без использования DOM и с его применением:
| Без DOM и JavaScript | С использованием DOM и JavaScript |
|---|---|
| Статичное содержимое | Динамическое содержимое |
| Необходимость перезагружать страницу для обновления данных | Обновление данных "на лету" |
| Ограниченные возможности взаимодействия | Богатые интерактивные возможности |
| Простые формы с переходами между страницами | Сложные формы с валидацией и мгновенной обратной связью |
DOM превращает статичный HTML в живой организм, который может реагировать на действия пользователя и изменяться без перезагрузки страницы — это основа современной веб-разработки. 🌐

Структура DOM-дерева: узлы, элементы и атрибуты
DOM представляет HTML-документ как иерархическое дерево объектов. Понимание структуры этого дерева критически важно для эффективной работы с ним. Каждый элемент в дереве — это узел (node), а узлы бывают разных типов.
Основные типы узлов в DOM-дереве:
- Document — корневой узел, представляющий весь документ (объект
document) - Element nodes — узлы элементов, представляющие HTML-теги
- Text nodes — текстовые узлы, содержащие текст внутри элементов
- Attribute nodes — узлы атрибутов, содержащие атрибуты элементов
- Comment nodes — узлы комментариев, представляющие HTML-комментарии
Иерархия DOM начинается с объекта document. От него идёт элемент html, который содержит два дочерних элемента: head и body. Внутри этих элементов находятся все остальные элементы страницы.
Рассмотрим соответствие между HTML-кодом и DOM-структурой:
<html>
<head>
<title>Моя страница</title>
</head>
<body>
<div id="container">
<h1>Привет, мир!</h1>
<p>Это <strong>важный</strong> параграф.</p>
</div>
</body>
</html>
Этот HTML-код формирует следующую DOM-структуру:
- document
- html
- head
- title
- текстовый узел: "Моя страница"
- body
- div (с атрибутом id="container")
- h1
- текстовый узел: "Привет, мир!"
- p
- текстовый узел: "Это "
- strong
- текстовый узел: "важный"
- текстовый узел: " параграф."
Для работы с узлами DOM предоставляет ряд свойств:
| Свойство | Описание | Пример использования |
|---|---|---|
| parentNode | Родительский узел | element.parentNode |
| childNodes | Коллекция дочерних узлов | element.childNodes |
| firstChild | Первый дочерний узел | element.firstChild |
| lastChild | Последний дочерний узел | element.lastChild |
| nextSibling | Следующий узел того же уровня | element.nextSibling |
| previousSibling | Предыдущий узел того же уровня | element.previousSibling |
| nodeType | Тип узла (1 – элемент, 3 – текст) | element.nodeType |
| nodeName | Имя узла (для элементов – имя тега) | element.nodeName |
Каждый элемент также может иметь атрибуты — дополнительные свойства, определяющие характеристики элемента. Доступ к атрибутам осуществляется через методы:
element.getAttribute('attr')— получить значение атрибутаelement.setAttribute('attr', 'value')— установить значение атрибутаelement.hasAttribute('attr')— проверить наличие атрибутаelement.removeAttribute('attr')— удалить атрибут
Понимание структуры DOM-дерева — это фундамент, на котором строится вся дальнейшая работа с DOM. Чем лучше вы представляете эту структуру, тем эффективнее сможете манипулировать элементами веб-страницы. 🌳
Методы поиска и выбора элементов в DOM
Для манипуляций с DOM первым шагом всегда является выбор элемента или группы элементов, с которыми вы планируете работать. JavaScript предлагает несколько методов для поиска элементов в DOM-дереве.
Основные методы выбора элементов:
document.getElementById('id')— выбирает элемент по его iddocument.getElementsByClassName('class')— выбирает элементы по имени классаdocument.getElementsByTagName('tag')— выбирает элементы по имени тегаdocument.querySelector('selector')— выбирает первый элемент, соответствующий CSS-селекторуdocument.querySelectorAll('selector')— выбирает все элементы, соответствующие CSS-селектору
Сравним эффективность и применимость различных методов выбора элементов:
| Метод | Возвращаемое значение | Производительность | Гибкость |
|---|---|---|---|
| getElementById | Один элемент или null | Очень высокая | Низкая (только по id) |
| getElementsByClassName | Живая HTMLCollection | Высокая | Средняя (только по классу) |
| getElementsByTagName | Живая HTMLCollection | Высокая | Средняя (только по тегу) |
| querySelector | Один элемент или null | Средняя | Высокая (любой CSS-селектор) |
| querySelectorAll | Статическая NodeList | Средняя | Высокая (любой CSS-селектор) |
Примеры использования методов выбора элементов:
// Выбор по id
const container = document.getElementById('container');
// Выбор по классу
const items = document.getElementsByClassName('item');
// Выбор по тегу
const paragraphs = document.getElementsByTagName('p');
// Выбор с помощью CSS-селектора (первое совпадение)
const firstButton = document.querySelector('.btn-primary');
// Выбор всех элементов, соответствующих селектору
const allInputs = document.querySelectorAll('input[type="text"]');
Максим Васильев, JavaScript-тренер
На моих курсах по веб-разработке я часто сталкиваюсь с тем, что начинающие разработчики не понимают разницу между методами выбора элементов и когда какой использовать. Один из моих студентов работал над проектом табло спортивных результатов, и страница сильно тормозила при обновлении данных.
Проанализировав его код, я обнаружил, что он использовал
querySelectorAllв цикле внутри обработчика события, который запускался каждую секунду, вместо того чтобы выбрать элементы один раз вне цикла и сохранить их в переменную.После оптимизации кода производительность страницы возросла в несколько раз. Этот случай стал отличным примером для всей группы о важности правильного выбора метода DOM-манипуляций и понимания их воздействия на производительность.
Важно понимать различия между возвращаемыми значениями разных методов:
- getElementById возвращает один элемент или
null - getElementsByClassName и getElementsByTagName возвращают "живую" коллекцию HTMLCollection, которая автоматически обновляется при изменении DOM
- querySelector возвращает первый найденный элемент или
null - querySelectorAll возвращает статическую коллекцию NodeList, которая не обновляется при изменении DOM
Если вам нужно работать с выбранными элементами как с массивом (например, использовать методы map, filter), то коллекции HTMLCollection и NodeList нужно преобразовать в массив:
// Преобразование HTMLCollection в массив
const itemsArray = Array.from(document.getElementsByClassName('item'));
// Или с помощью spread-оператора
const paragraphsArray = [...document.getElementsByTagName('p')];
// Теперь можно использовать методы массивов
itemsArray.forEach(item => {
item.style.color = 'red';
});
Выбор правильного метода поиска элементов зависит от конкретной задачи. Для максимальной производительности используйте getElementById или getElementsByClassName, если вам нужна гибкость — querySelector и querySelectorAll с CSS-селекторами. 🔍
Изменение содержимого и стилей элементов через DOM
После того как вы научились находить элементы в DOM, следующим шагом является изменение их содержимого и внешнего вида. JavaScript предоставляет множество свойств и методов для манипуляции содержимым и стилями элементов.
Основные способы изменения содержимого элементов:
element.textContent— изменяет текстовое содержимое элементаelement.innerHTML— изменяет HTML-содержимое элементаelement.innerText— изменяет видимый текст элемента (с учетом CSS)element.outerHTML— изменяет HTML элемента вместе с самим элементом
Примеры манипуляции содержимым:
// Получаем элемент
const header = document.getElementById('title');
// Изменяем текстовое содержимое
header.textContent = 'Новый заголовок';
// Изменяем HTML-содержимое
header.innerHTML = 'Новый <span class="highlight">заголовок</span>';
// Получаем параграф и изменяем его текст
const paragraph = document.querySelector('p');
paragraph.innerText = 'Этот текст заменит предыдущее содержимое параграфа.';
Важно различие между этими свойствами:
textContent— просто текст, HTML-теги будут экранированыinnerHTML— интерпретирует HTML-теги, создавая соответствующие DOM-элементыinnerText— учитывает стилевое форматирование и видимость элементов
Для изменения стилей элементов можно использовать свойство style или манипулировать классами:
// Прямое изменение стилей
const box = document.querySelector('.box');
box.style.backgroundColor = 'blue';
box.style.width = '200px';
box.style.padding = '20px';
box.style.borderRadius = '10px';
// Использование классов (более предпочтительный подход)
box.classList.add('highlighted'); // Добавить класс
box.classList.remove('hidden'); // Удалить класс
box.classList.toggle('active'); // Переключить класс
box.classList.contains('selected'); // Проверить наличие класса
Работа с атрибутами элементов также часто требуется при DOM-манипуляциях:
const link = document.querySelector('a');
// Установка атрибутов
link.setAttribute('href', 'https://example.com');
link.setAttribute('target', '_blank');
// Получение атрибутов
const linkUrl = link.getAttribute('href');
// Проверка наличия атрибута
if (link.hasAttribute('target')) {
console.log('Ссылка открывается в новом окне');
}
// Удаление атрибута
link.removeAttribute('target');
Сравнение подходов к изменению стилей элементов:
| Подход | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
| Прямое изменение style | Простота, немедленный эффект | Смешивание логики и представления, затруднение поддержки | Для временных, динамических изменений |
| Манипуляция классами | Разделение логики и стилей, легкость поддержки | Требует предопределенных CSS-классов | Для большинства случаев, особенно при переключении состояний |
| Установка атрибутов | Подходит для специфичных атрибутов (src, href) | Менее гибкий для стилизации | Для работы с атрибутами, не относящимися к стилям |
| CSS-переменные | Мощный, централизованный контроль тем | Не поддерживается старыми браузерами | Для сложных тем и состояний интерфейса |
Несколько практических советов по работе с DOM-манипуляциями:
- Предпочитайте
classListвместо прямого изменения стилей — это обеспечивает лучшую организацию кода и разделение обязанностей - Избегайте частого использования
innerHTMLдля динамического контента — это может создавать уязвимости XSS - Группируйте DOM-операции для повышения производительности — каждое изменение DOM вызывает перерисовку
- Используйте
textContentвместоinnerTextдля лучшей производительности, если не требуется учитывать видимость
Изменение содержимого и стилей элементов — мощный инструмент для создания динамических интерфейсов. Правильное использование этих методов позволяет создавать отзывчивые и интерактивные веб-приложения без перезагрузки страницы. 🎨
Практика: создание и удаление элементов в JavaScript
Создание и удаление элементов "на лету" — одна из самых мощных возможностей DOM API. Это позволяет динамически изменять структуру страницы в ответ на действия пользователя или другие события. Давайте рассмотрим, как создавать новые элементы, добавлять их в DOM и удалять существующие элементы.
Основные методы для создания и добавления элементов:
document.createElement('tag')— создает новый HTML-элементdocument.createTextNode('text')— создает текстовый узелparentElement.appendChild(newElement)— добавляет элемент в конец родительского элементаparentElement.insertBefore(newElement, referenceElement)— вставляет элемент перед указаннымelement.append(...nodes)— добавляет набор узлов или строк в конец элементаelement.prepend(...nodes)— добавляет набор узлов или строк в начало элемента
Методы для удаления элементов:
parentElement.removeChild(element)— удаляет дочерний элементelement.remove()— удаляет сам элемент (современный метод)
Давайте рассмотрим практический пример создания и добавления элемента:
// Создаем новый элемент списка
const newItem = document.createElement('li');
// Создаем текстовый узел и добавляем его в элемент списка
const textNode = document.createTextNode('Новый пункт списка');
newItem.appendChild(textNode);
// Альтернативно, можно установить textContent
// newItem.textContent = 'Новый пункт списка';
// Добавляем класс к новому элементу
newItem.classList.add('list-item');
// Устанавливаем дополнительные атрибуты
newItem.setAttribute('data-id', '123');
// Находим список, в который нужно добавить элемент
const list = document.getElementById('todo-list');
// Добавляем новый элемент в конец списка
list.appendChild(newItem);
Более современный подход с использованием append и prepend:
// Создаем новый элемент
const newHeader = document.createElement('h2');
newHeader.textContent = 'Новый заголовок';
// Создаем еще один элемент
const newParagraph = document.createElement('p');
newParagraph.textContent = 'Текст нового параграфа';
// Находим контейнер
const container = document.querySelector('.content');
// Добавляем оба элемента в начало контейнера
container.prepend(newHeader, newParagraph);
// Добавляем текст и элемент в конец контейнера
const anotherParagraph = document.createElement('p');
anotherParagraph.textContent = 'Еще один параграф';
container.append('Просто текст', anotherParagraph);
Теперь рассмотрим пример удаления элементов:
// Удаление элемента через его родителя
const itemToRemove = document.querySelector('.item-to-remove');
const parent = itemToRemove.parentNode;
parent.removeChild(itemToRemove);
// Современный способ удаления элемента напрямую
const anotherItemToRemove = document.querySelector('.another-item');
anotherItemToRemove.remove();
// Удаление всех дочерних элементов
const container = document.querySelector('.container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// Альтернативно, можно просто очистить содержимое
// container.innerHTML = '';
Практический пример создания и удаления элементов — интерактивный список задач:
// Функция для добавления новой задачи
function addTask() {
// Получаем текст из поля ввода
const inputField = document.getElementById('new-task');
const taskText = inputField.value.trim();
if (taskText !== '') {
// Создаем новый элемент списка
const taskItem = document.createElement('li');
taskItem.className = 'task-item';
// Создаем текстовый span
const taskTextSpan = document.createElement('span');
taskTextSpan.textContent = taskText;
taskItem.appendChild(taskTextSpan);
// Создаем кнопку удаления
const deleteButton = document.createElement('button');
deleteButton.textContent = 'Удалить';
deleteButton.className = 'delete-btn';
// Добавляем обработчик для удаления
deleteButton.addEventListener('click', function() {
taskItem.remove();
});
// Добавляем кнопку в элемент списка
taskItem.appendChild(deleteButton);
// Добавляем элемент в список задач
const taskList = document.getElementById('task-list');
taskList.appendChild(taskItem);
// Очищаем поле ввода
inputField.value = '';
}
}
// Прикрепляем обработчик события к кнопке добавления
const addButton = document.getElementById('add-task');
addButton.addEventListener('click', addTask);
Несколько важных моментов и практических советов:
- 💡 DocumentFragment: Для оптимизации производительности при добавлении множества элементов используйте
DocumentFragment— это контейнер, который не является частью активного DOM-дерева - 🚀 Клонирование элементов: Вместо создания новых элементов с нуля можно клонировать существующие с помощью
element.cloneNode(deep), гдеdeep— булево значение, указывающее, нужно ли клонировать всех потомков - ⚠️ Избегайте innerHTML для динамического добавления элементов, особенно с пользовательским вводом, так как это может создать уязвимости безопасности
- 🔄 Минимизируйте перерисовки: Группируйте DOM-операции и используйте
DocumentFragmentдля уменьшения количества перерисовок страницы
Создание и удаление элементов в DOM — это основа для разработки динамических веб-приложений. Освоив эти техники, вы сможете создавать интерактивные интерфейсы, которые реагируют на действия пользователей и обновляются без перезагрузки страницы. 🛠️
DOM — это не просто набор инструментов, а настоящая платформа для превращения статичных веб-страниц в живые приложения. От простого выбора элементов до создания динамического контента и интерактивных компонентов — DOM открывает огромные возможности для JavaScript-разработчиков. Овладев основами манипуляции DOM, вы сделаете фундаментальный шаг в своём развитии как веб-разработчик. Помните, что практика — ключ к мастерству. Начните с малого, создайте простое интерактивное приложение, и постепенно вы увидите, как технологии DOM-манипуляций трансформируют ваш подход к веб-разработке.
Станислав Плотников
фронтенд-разработчик