DOM и события
Выбор элементов, безопасные изменения, события и делегирование.
Обновлено
Что такое DOM
DOM (Document Object Model) — представление страницы в виде дерева объектов, которое JavaScript может читать и менять. Браузер строит его из HTML; когда вы меняете его из JS, страница обновляется.
documenthtmlheadbodyheadermainulli«Яблоко»li«Груша»
HTML — это исходный текст; DOM — живое состояние страницы. Если JS добавит <li>, он появится в DOM (и в DevTools → Elements), но не в «Просмотре кода».
Виды узлов
| Узел | Пример |
|---|---|
document |
корень |
| элемент | <li>, <button> |
| текст | текст внутри элемента |
| комментарий | <!-- --> |
На практике работают почти только с элементами.
Выбор элементов
| Метод | Возвращает | Когда |
|---|---|---|
querySelector(css) |
первый элемент или null |
по умолчанию — принимает любой CSS-селектор |
querySelectorAll(css) |
NodeList (статический) |
несколько элементов; [...list] для map |
getElementById(id) |
один элемент | быстро, по id |
el.closest(css) |
ближайшего предка (или сам элемент) | делегирование событий |
Изменение
el.textContent = 'Безопасный текст' // ✓ текст, HTML не интерпретируется
el.innerHTML = '<b>HTML</b>' // ⚠️ интерпретирует HTML — XSS с данными пользователя
el.classList.add('active') // .remove / .toggle / .contains
el.dataset.id // читает data-id="..."
el.setAttribute('aria-expanded', 'true')
el.style.setProperty('--progress', '40%')
parent.append(child); el.remove()textContent или innerHTML: первое — для текста (безопасно), второе — для доверенного HTML. Разница — в безопасности, см. XSS.
События
Событие — сигнал, что что-то произошло: клик, клавиша, отправка формы, прокрутка. Его слушают обработчиком (listener):
button.addEventListener('click', event => {
console.log(event.target) // элемент, по которому кликнули
})| Вид | Примеры |
|---|---|
| мышь / указатель | click, pointerdown, mouseenter |
| клавиатура | keydown, keyup |
| форма | submit, input, change, focus, blur |
| окно | resize, scroll, load |
Распространение: capture и всплытие
Клик по <li> принадлежит не только ему. Событие спускается от document до <li> (capture), затем поднимается обратно (всплытие) через ul, main, body… Его получает каждый обработчик по пути.
| Свойство / метод | Роль |
|---|---|
event.target |
элемент, где это произошло (самый глубокий) |
event.currentTarget |
элемент, у которого есть обработчик |
event.preventDefault() |
отменяет стандартное поведение (отправку, переход по ссылке) |
event.stopPropagation() |
останавливает всплытие (нужно редко) |
Делегирование событий
Благодаря всплытию можно поставить один обработчик на родителя вместо обработчика на каждом ребёнке:
list.addEventListener('click', e => {
const item = e.target.closest('[data-id]')
if (item) remove(item.dataset.id)
})Работает и для элементов, добавленных позже, и расходует меньше памяти.
Формы
form.addEventListener('submit', e => {
e.preventDefault() // без перезагрузки
const data = Object.fromEntries(new FormData(e.currentTarget))
})Связь с React
React строит и обновляет DOM за вас, декларативно: вы описываете, как должен выглядеть интерфейс, React вносит изменения. Но onClick, event.target, preventDefault, FormData, всплытие — это те же самые API. React даже использует делегирование событий в корне приложения.
Коротко
- DOM = живое дерево страницы, которое можно менять из JS.
querySelector+closest;textContentдля текста,innerHTML— только с доверенным HTML.- События всплывают → делегирование с одним обработчиком на родителе.