JavaScript и DOM
Узнайте, как получать доступ, обновлять и манипулировать DOM с помощью JavaScript: выбирайте элементы, изменяйте контент, стили и обрабатывайте события.
У нас есть отдельный полный раздел о JavaScript DOM. В нём можно найти подробные примеры и объяснения.
Введение в JavaScript и DOM
JavaScript — это язык сценариев, который оживляет веб-страницы. Document Object Model (DOM) — это мост, позволяющий ему делать это: когда браузер загружает документ HTML, он разбирает разметку в живое дерево объектов в памяти. JavaScript читает и изменяет это дерево, а браузер мгновенно перерисовывает страницу в соответствии с изменениями. Именно так статический документ становится интерактивным — кнопки реагируют, контент обновляется, а стили меняются без перезагрузки.
На этой странице рассматриваются основы: структура DOM, методы выбора элементов, изменение контента и стилей, а также обработка пользовательских событий. Каждая тема содержит ссылки на более подробные главы для углублённого изучения.
Понимание DOM
DOM — это структурированное древовидное представление вашего HTML-документа. Каждый тег, атрибут и фрагмент текста становится узлом — объектом, который JavaScript может читать и изменять. Поскольку дерево живое, изменение узла немедленно отображается для пользователя.
Полезно различать три термина, которые легко перепутать:
- DOM — объектная модель, которую браузер строит из вашего HTML. Это не исходный HTML-код; это разобранная и нормализованная версия документа в браузере.
document— глобальный объект, являющийся точкой входа в дерево DOM. Каждый запрос начинается здесь (или от другого элемента).- Node (Узел) — единственная точка в дереве. Элементы (
<div>,<p>), текст и комментарии — всё это узлы; чаще всего вы работаете с узлами-элементами.
Для более подробного изучения типов узлов и структуры дерева смотрите Понимание узлов DOM и Обход DOM.
Навигация по дереву DOM
JavaScript предоставляет несколько методов для поиска элементов в дереве, чтобы вы могли с ними работать.
Дерево ниже имеет корень document, элемент <html> с дочерними <head> и <body>, а также текстовые узлы внутри заголовков и абзацев:
<!DOCTYPE html>
<html>
<head>
<title>Text</title>
</head>
<body>
<h1>Header</h1>
<p>Paragraph</p>
</body>
</html>Основные методы выбора
document.getElementById()— возвращает единственный элемент с указаннымidилиnull, если он не найден.document.getElementsByClassName()— возвращает живуюHTMLCollectionэлементов с указанным классом.document.getElementsByTagName()— возвращает живуюHTMLCollectionэлементов с указанным тегом.document.querySelector()— возвращает первый элемент, соответствующий любому CSS-селектору, илиnull.document.querySelectorAll()— возвращает статическийNodeListвсех подходящих элементов.
Какой метод использовать? В современном коде querySelector и querySelectorAll покрывают почти все случаи, поскольку поддерживают полный синтаксис CSS-селекторов (#id, .class, div > p, [type="text"]). Используйте getElementById только когда нужен максимально быстрый поиск по известному id.
На практике важны два различия:
- Живые и статические. Живая
HTMLCollection(изgetElementsBy*) обновляется автоматически при изменении DOM; статическийNodeList(изquerySelectorAll) — это снимок, сделанный в момент вызова. - Итерация.
NodeListподдерживаетforEachнапрямую;HTMLCollection— нет, поэтому сначала преобразуйте её с помощьюArray.from(collection).
Подробнее см. Выбор элементов DOM.
Манипуляции с элементами DOM
Получив ссылку на элемент, вы можете изменить его содержимое, атрибуты и внешний вид — страница обновляется мгновенно.
Основные операции
- Изменение содержимого: используйте
element.innerHTMLилиelement.textContent. - Изменение стилей: обращайтесь к свойству
element.style. - Создание элементов: используйте
document.createElement(). - Добавление элементов: используйте
parentElement.appendChild(newElement). - Удаление элементов: используйте
parentElement.removeChild(existingElement).
innerHTML разбирает строку как HTML, поэтому вставка ненадёжного ввода открывает уязвимость XSS. Используйте textContent, когда вставляете простой текст — это и безопаснее, и быстрее.
Более подробное описание см. в Манипуляции с DOM и Работа со стилями в DOM.
Обработка событий в JavaScript
Событие — это что-то, что происходит на странице: клик, нажатие клавиши, отправка формы, завершение загрузки страницы. JavaScript может зарегистрировать слушатель, который запускает функцию всякий раз, когда заданное событие происходит на заданном элементе.
Синтаксис слушателя событий
element.addEventListener('event', functionToCall);Первый аргумент — имя события (без префикса on — это 'click', а не 'onclick'). Второй — обработчик, функция, которую браузер вызывает при наступлении события.
Ключевые события
- События клика: срабатывают при кликах пользователя.
- События загрузки: возникают при загрузке ресурсов.
- События ввода: происходят при взаимодействии пользователя с полями ввода.
Пример обработки событий
<!DOCTYPE html>
<html>
<head>
<title>Event Handling</title>
</head>
<body>
<button id="clickMe">Click Me</button>
<script>
document.getElementById('clickMe').addEventListener('click', function() {
alert('Button Clicked!');
});
</script>
</body>
</html>Для более широкого знакомства с моделью событий — всплытием, объектом события и удалением слушателей — прочтите Введение в события браузера и Обработка событий в DOM.
Продвинутые манипуляции с DOM
Помимо базовых операций, JavaScript поддерживает более сложные действия, такие как клонирование узлов, работа с формами и переключение CSS-классов.
Техники
- Клонирование узлов —
element.cloneNode(true)копирует элемент вместе с его потомками (falseкопирует только сам элемент). - Обработка форм — читайте
input.value, реагируйте наsubmitи выполняйте валидацию перед отправкой. - Управление CSS-классами —
element.classList.add(),.remove()и.toggle()удобнее, чем перезаписьclassName.
API classList — это идиоматический способ включать и выключать стили. Следующий запускаемый фрагмент показывает логику, которой следует toggle:
// classList.toggle removes a class if present, adds it if absent.
// Here we model that behaviour with a plain Set to show the result.
const classes = new Set(['box']);
function toggle(name) {
if (classes.has(name)) {
classes.delete(name);
} else {
classes.add(name);
}
return classes.has(name);
}
console.log(toggle('active')); // true (added)
console.log(toggle('active')); // false (removed)
console.log([...classes]); // [ 'box' ]JavaScript и DOM: лучшие практики
Чтобы эффективно использовать DOM, помните следующее:
- Минимизируйте обращения к DOM. Чтение и запись в DOM намного медленнее, чем работа с JavaScript-значениями. Кэшируйте ссылки и группируйте изменения, а не обращайтесь к DOM в плотном цикле.
- Используйте делегирование событий. Вместо одного слушателя на каждый дочерний элемент, прикрепите один слушатель к родителю и проверяйте
event.target. Это автоматически обрабатывает динамически добавленные дочерние элементы и потребляет меньше памяти. - Понимайте reflow и repaint. Reflow пересчитывает разметку; repaint перерисовывает пиксели. Оба процесса ресурсоёмки, поэтому группируйте записи стилей и предпочитайте
DocumentFragmentдля массовых вставок. См. Оптимизация производительности DOM.
Пример делегирования событий
Вместо того чтобы привязывать обработчик к каждому <li>, привяжите один к списку и определяйте, на какой элемент кликнул пользователь:
document.getElementById('list').addEventListener('click', function (event) {
// event.target is the actual element the user clicked.
if (event.target.tagName === 'LI') {
console.log('You clicked:', event.target.textContent);
}
});JavaScript и DOM: примеры кода
Изменение содержимого
<!DOCTYPE html>
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<div id="content">Original Content</div>
<script>
document.getElementById('content').innerHTML = 'Updated Content';
</script>
</body>
</html>Добавление новых элементов
<!DOCTYPE html>
<html>
<head>
<title>Add Elements</title>
</head>
<body>
<div id="container"></div>
<script>
var newElement = document.createElement('p');
newElement.textContent = 'New Paragraph';
document.getElementById('container').appendChild(newElement);
</script>
</body>
</html>Помните: освоение JavaScript и DOM — это непрерывный путь обучения. Продолжайте экспериментировать, создавать проекты и совершенствовать свои навыки, чтобы стать опытным JavaScript-разработчиком.