Работа с элементами DOM в JavaScript: основы и методы для новичков
#Веб-разработка #Основы JavaScript #Работа с DOMДля кого эта статья:
- Начинающие разработчики, желающие освоить работу с DOM в JavaScript
- Студенты и ученики, изучающие веб-разработку и программирование
- Профессионалы, желающие улучшить свои навыки динамического манипулирования элементами на веб-страницах
Освоить работу с DOM — всё равно что получить ключи от города веб-разработки. Это тот фундаментальный навык, который превращает статичные HTML-страницы в живые, реагирующие на пользователя интерфейсы. Я ежедневно наблюдаю, как начинающие разработчики спотыкаются именно здесь: понимая основы JavaScript, они теряются, когда нужно найти элемент на странице, изменить его содержимое или добавить обработчик событий. Давайте разберёмся с этими базовыми техниками работы с DOM раз и навсегда — так, чтобы у вас больше не возникало вопросов "как это работает?" 🚀
Что такое DOM и почему он важен для JavaScript-разработки
Document Object Model (DOM) — это программный интерфейс для HTML и XML документов, представляющий их в виде древовидной структуры, где каждый узел является объектом, представляющим часть документа. По сути, DOM — это мост между вашим JavaScript-кодом и HTML-страницей.
Когда браузер загружает веб-страницу, он создаёт DOM документа — объектную модель HTML-страницы в памяти. JavaScript может обращаться к этой модели и изменять её, что позволяет динамически обновлять содержимое, структуру и стили страницы без перезагрузки.
Андрей Соколов, Lead Frontend Developer
Помню свой первый серьёзный проект — административную панель для сети ресторанов. Клиент хотел, чтобы интерфейс был интерактивным: перетаскивание элементов меню, моментальное обновление статусов заказов, редактирование информации без перезагрузки страницы.
Я был уверен в своих знаниях JavaScript, но когда дело дошло до практики, столкнулся с тем, что не понимаю, как правильно взаимодействовать с элементами на странице. Проблема была в том, что я не осознавал, как работает DOM.
Первый прототип был медленным и нестабильным — я использовал прямые манипуляции с innerHTML для каждого изменения, что приводило к полной перерисовке компонентов и потере состояния элементов. После углубленного изучения DOM я переписал интерфейс, используя точечные изменения элементов, создание и удаление узлов только когда это необходимо.
Результат превзошёл ожидания: интерфейс стал отзывчивым, потребление памяти снизилось, а клиент получил именно то, что хотел — плавную и быструю систему управления.
Итак, почему DOM так важен для JavaScript-разработчика? Рассмотрим ключевые причины:
- Динамическое обновление контента — изменение текста, изображений и других элементов без перезагрузки страницы
- Управление стилями и классами — возможность изменять внешний вид элементов
- Взаимодействие с пользователем — обработка событий (клики, нажатия клавиш, движения мыши)
- Валидация данных форм — проверка введённых пользователем данных перед отправкой
- Создание и удаление элементов — динамическое формирование структуры страницы
| Концепция | Традиционный подход | Подход с использованием DOM |
|---|---|---|
| Обновление данных | Перезагрузка всей страницы | Точечное обновление конкретных элементов |
| Взаимодействие с сервером | Каждое действие = новый запрос страницы | Асинхронные запросы без перезагрузки (AJAX) |
| Пользовательский опыт | Прерывистый (ожидание загрузки) | Плавный и непрерывный |
| Производительность | Повышенная нагрузка на сервер | Распределение нагрузки между клиентом и сервером |
DOM представляет страницу как дерево узлов, где каждый HTML-элемент является узлом. Даже текст внутри элементов и комментарии — отдельные узлы этого дерева. Понимание этой структуры критически важно для эффективной работы с JavaScript.

Поиск и выбор элементов на веб-странице с помощью JavaScript
Первый шаг в работе с DOM — найти нужный элемент. JavaScript предоставляет несколько мощных методов для этого, от базовых до продвинутых. Выбор правильного метода может значительно повлиять на производительность вашего приложения.
Изменение содержимого и атрибутов DOM-элементов
После того как вы научились находить элементы, следующий логический шаг — изменение их содержимого и атрибутов. JavaScript предоставляет несколько способов модификации DOM-элементов, каждый со своими особенностями и применениями.
Основные способы изменения содержимого элементов:
element.innerHTML— изменяет HTML внутри элементаelement.textContent— изменяет только текстовое содержимоеelement.innerText— похож на textContent, но учитывает стили и видимость
Рассмотрим примеры:
// HTML: <div id="content">Старый текст</div>
// Изменение через innerHTML (интерпретирует HTML-теги)
document.getElementById("content").innerHTML = "<strong>Новый</strong> текст";
// Результат: <strong>Новый</strong> текст
// Изменение через textContent (безопаснее, не интерпретирует HTML)
document.getElementById("content").textContent = "<strong>Новый</strong> текст";
// Результат: <strong>Новый</strong> текст (как обычный текст)
Для работы с атрибутами элементов существуют следующие основные методы:
element.getAttribute(name)— получает значение атрибутаelement.setAttribute(name, value)— устанавливает значение атрибутаelement.removeAttribute(name)— удаляет атрибут- Прямой доступ через свойства для стандартных атрибутов:
element.id,element.src,element.hrefи т.д.
// Установка и получение атрибутов
const link = document.querySelector("a");
link.setAttribute("href", "https://example.com");
link.setAttribute("target", "_blank");
console.log(link.getAttribute("href")); // https://example.com
// Прямой доступ к стандартным атрибутам
link.href = "https://newexample.com";
link.id = "main-link";
Для работы со стилями элементов используются следующие подходы:
element.style.property— прямое изменение стилейelement.className— изменение всего списка классов (строкой)element.classList— объект с методами для управления классами
// Изменение стилей напрямую
const div = document.getElementById("box");
div.style.backgroundColor = "blue";
div.style.width = "200px";
div.style.marginTop = "20px";
// Работа с классами
div.className = "highlight box"; // заменит все существующие классы
// Более гибкий подход через classList
div.classList.add("highlight"); // добавляет класс
div.classList.remove("box"); // удаляет класс
div.classList.toggle("active"); // переключает класс
div.classList.contains("highlight"); // проверяет наличие класса
| Метод изменения | Преимущества | Недостатки | Лучшее применение |
|---|---|---|---|
| innerHTML | Простота использования, возможность вставки HTML | Риски XSS-атак, полная перерисовка содержимого | Когда нужно вставить HTML-разметку |
| textContent | Безопасность, высокая производительность | Невозможность вставки форматированного текста | Для простого текстового контента |
| style.property | Точечное изменение конкретных стилей | Смешивание логики и представления | Для динамических визуальных эффектов |
| classList | Чистое разделение логики и стилей | Требует предопределенных CSS-классов | Большинство случаев изменения внешнего вида |
При изменении содержимого и атрибутов важно помнить о производительности. Каждая операция с DOM вызывает перерисовку (reflow/repaint), что может замедлить работу страницы при частых изменениях. Для оптимизации используйте следующие рекомендации:
- Группируйте изменения, минимизируя количество обращений к DOM
- Используйте фрагменты документа для пакетного добавления элементов
- Предпочитайте изменение классов прямому изменению стилей
- Кэшируйте ссылки на часто используемые элементы в переменных
Создание и удаление элементов DOM программным путём
Динамическое создание и удаление элементов — мощная возможность, позволяющая гибко формировать содержимое страницы в ответ на действия пользователя или получение данных. Эта техника лежит в основе современных интерактивных веб-приложений. 🛠️
Основные методы для создания элементов:
document.createElement(tagName)— создаёт новый элементdocument.createTextNode(text)— создаёт текстовый узелdocument.createDocumentFragment()— создаёт невидимый контейнер для группировки элементов
Методы для добавления элементов в DOM:
parentNode.appendChild(node)— добавляет узел в конец списка дочерних элементовparentNode.insertBefore(newNode, referenceNode)— вставляет перед указанным узломparentNode.append(...nodes)— добавляет набор узлов или строк в конецparentNode.prepend(...nodes)— добавляет в началоreferenceNode.before(...nodes)— вставляет перед указанным узломreferenceNode.after(...nodes)— вставляет после указанного узла
Методы для удаления элементов:
parentNode.removeChild(node)— удаляет указанный дочерний элементnode.remove()— удаляет сам элемент (современный метод)
Вот пример создания и добавления нового элемента:
// Создание нового элемента списка
const newItem = document.createElement("li");
newItem.textContent = "Новый пункт списка";
newItem.className = "list-item";
// Добавление элемента в список
const list = document.getElementById("myList");
list.appendChild(newItem);
// Современный способ с использованием append
list.append(newItem);
// Создание нескольких элементов и добавление их вместе
const item1 = document.createElement("li");
item1.textContent = "Первый пункт";
const item2 = document.createElement("li");
item2.textContent = "Второй пункт";
list.append(item1, item2, "Можно добавить и текст");
Для более сложных случаев, когда нужно добавить много элементов, оптимально использовать DocumentFragment, чтобы минимизировать перерисовки страницы:
// Создание фрагмента для хранения элементов
const fragment = document.createDocumentFragment();
// Добавление элементов во фрагмент
for (let i = 0; i < 100; i++) {
const item = document.createElement("li");
item.textContent = `Пункт ${i + 1}`;
fragment.appendChild(item);
}
// Добавление всего фрагмента за одну операцию
document.getElementById("myList").appendChild(fragment);
Удаление элементов также может быть выполнено различными способами:
// Традиционный способ удаления элемента
const parent = document.getElementById("container");
const childToRemove = document.getElementById("oldElement");
parent.removeChild(childToRemove);
// Современный способ
document.getElementById("anotherElement").remove();
// Удаление всех дочерних элементов
const list = document.getElementById("myList");
while (list.firstChild) {
list.removeChild(list.firstChild);
}
// Или более современный способ
list.innerHTML = "";
Важный аспект при создании элементов — клонирование существующих. Это может быть полезно, когда нужно создать несколько похожих элементов:
// Клонирование элемента
const original = document.getElementById("templateItem");
const clone = original.cloneNode(true); // true для глубокого клонирования
clone.id = "newId"; // важно изменить ID
document.getElementById("anotherList").appendChild(clone);
Марина Петрова, Frontend Developer
Однажды я работала над проектом интерактивной галереи товаров для интернет-магазина. По требованиям, пользователь должен был видеть первые 10 товаров, а остальные подгружались динамически по мере прокрутки страницы.
Первая версия сильно тормозила при добавлении новых карточек товаров. Я создавала каждый элемент через createElement и сразу добавляла его в DOM, что вызывало множество перерисовок.
Проблему удалось решить двумя способами: во-первых, я стала использовать DocumentFragment для группировки элементов перед вставкой; во-вторых, реализовала систему переиспользования элементов — когда карточка товара скрывалась за пределами экрана, она не удалялась, а перемещалась в конец списка с новыми данными.
Это преобразило работу галереи — даже на слабых устройствах прокрутка стала плавной, а потребление памяти значительно снизилось. Я поняла важный урок: при работе с DOM критически важно не только что делать, но и как это делать.
События DOM и практика их обработки в JavaScript
Обработка событий — ключевой аспект создания интерактивных веб-приложений. События DOM позволяют JavaScript-коду реагировать на действия пользователя и изменения на странице. 👩💻
Основные способы назначения обработчиков событий:
element.addEventListener(event, handler[, options])— современный и рекомендуемый методelement.onevent = function() {}— прямое присваивание (только один обработчик)- Атрибуты HTML
<button onclick="...">(не рекомендуется, смешивает HTML и JS)
Рассмотрим базовые примеры обработки событий:
// Добавление обработчика клика
const button = document.getElementById("myButton");
button.addEventListener("click", function(event) {
console.log("Кнопка нажата!");
console.log(event); // объект события содержит полезную информацию
});
// Обработка события с использованием стрелочной функции
document.getElementById("myInput").addEventListener("input", (e) => {
console.log(`Введено: ${e.target.value}`);
});
// Удаление обработчика (нужна ссылка на функцию)
function handleHover() {
console.log("Наведение");
}
const element = document.querySelector(".hoverable");
element.addEventListener("mouseover", handleHover);
// Позже, когда обработчик больше не нужен:
element.removeEventListener("mouseover", handleHover);
Наиболее часто используемые типы событий:
- Мышь: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout
- Клавиатура: keydown, keyup, keypress
- Формы: submit, change, input, focus, blur
- Документ: DOMContentLoaded, load, resize, scroll
- Сенсорные: touchstart, touchmove, touchend
Один из ключевых аспектов при работе с событиями — это понимание всплытия событий (event bubbling) и их распространения. Когда событие происходит на элементе, оно сначала срабатывает на нём, затем на его родителе и так далее вверх по дереву DOM.
// Остановка всплытия события
element.addEventListener("click", function(event) {
event.stopPropagation(); // Предотвращает всплытие события к родителям
// Обработка события здесь
});
// Предотвращение действия по умолчанию
document.getElementById("myLink").addEventListener("click", function(event) {
event.preventDefault(); // Предотвращает переход по ссылке
console.log("Переход предотвращен");
});
Делегирование событий — мощная техника, позволяющая оптимизировать работу с множеством однотипных элементов:
// Вместо добавления обработчика к каждой кнопке
document.querySelector(".container").addEventListener("click", function(event) {
// Проверяем, что клик был по кнопке
if (event.target.matches("button") || event.target.closest("button")) {
console.log("Нажата кнопка:", event.target.textContent);
// Дальнейшая обработка...
}
});
Преимущества делегирования событий:
- Экономия памяти — один обработчик вместо множества
- Автоматическая работа с новыми элементами, добавленными динамически
- Уменьшение количества кода и повышение его читаемости
Для более сложных пользовательских интерфейсов полезно понимать фазы распространения событий:
| Фаза | Описание | Как использовать |
|---|---|---|
| Захват | Событие сначала перехватывается корневым элементом и идёт вниз к цели | addEventListener(event, handler, true) |
| Цель | Событие достигает целевого элемента | Стандартная обработка |
| Всплытие | Событие возвращается обратно вверх от цели к корню | addEventListener(event, handler) — по умолчанию |
Практический пример — создание простого интерактивного списка дел:
// HTML:
// <div id="todo-app">
// <input id="new-todo" placeholder="Добавить задачу">
// <button id="add-todo">Добавить</button>
// <ul id="todo-list"></ul>
// </div>
// Получение элементов
const input = document.getElementById("new-todo");
const addButton = document.getElementById("add-todo");
const todoList = document.getElementById("todo-list");
// Добавление новой задачи
addButton.addEventListener("click", function() {
if (input.value.trim() === "") return;
// Создание нового элемента списка
const li = document.createElement("li");
li.innerHTML = `
<span class="todo-text">${input.value}</span>
<button class="delete-btn">Удалить</button>
<button class="complete-btn">Готово</button>
`;
todoList.appendChild(li);
input.value = "";
});
// Делегирование событий для управления задачами
todoList.addEventListener("click", function(event) {
const target = event.target;
// Обработка нажатия на кнопку удаления
if (target.classList.contains("delete-btn")) {
target.closest("li").remove();
}
// Обработка нажатия на кнопку "Готово"
if (target.classList.contains("complete-btn")) {
target.closest("li").querySelector(".todo-text").style.textDecoration = "line-through";
}
});
Дополнительные советы по работе с событиями:
- Используйте
removeEventListenerдля удаления ненужных обработчиков во избежание утечек памяти - Для сложных интерфейсов рассмотрите использование шаблона издатель-подписчик (pub/sub)
- В обработчиках событий форм не забывайте предотвращать отправку формы с помощью
preventDefault() - Используйте
debounceиthrottleдля оптимизации часто вызываемых событий (resize, scroll)
DOM — это не просто набор методов и свойств, а фундаментальный инструмент, который раскрывает весь потенциал JavaScript в браузере. Освоив базовые техники работы с DOM, вы получаете возможность создавать по-настоящему интерактивные и отзывчивые веб-приложения.
Начните с малого — научитесь уверенно находить элементы, изменять их содержимое, создавать новые компоненты интерфейса и обрабатывать события пользователя. Эти навыки станут основой для дальнейшего роста и освоения более продвинутых концепций веб-разработки.
Практикуйтесь каждый день, экспериментируйте с кодом и не бойтесь заглядывать под капот готовых решений — понимание работы DOM трансформирует ваш подход к созданию современных веб-интерфейсов.
Станислав Плотников
фронтенд-разработчик