# JavaScript DOM: Полное руководство по манипуляции элементами

Источник: https://www.youtube.com/watch?v=c6IyCwAV6BY
Канал: freeCodeCamp.org
Опубликовано: 16.10.2025

---

## Введение в DOM: фундамент интерактивного веба
[[JUMP:0:00]]

DOM (Document Object Model) — это ключевой программный интерфейс, связывающий JavaScript с HTML-страницей, что позволяет создавать динамичные и интерактивные пользовательские интерфейсы. Видеокурс от канала freeCodeCamp.org представляет собой исчерпывающее руководство для начинающих веб-разработчиков, охватывающее все аспекты: от глубокого понимания структуры документа до практической реализации полноценного приложения для отслеживания расходов (expense tracker). Автор курса подчёркивает, что глубокое знание DOM в сочетании с пониманием JavaScript, HTML и CSS является необходимым фундаментом современного веб-разработчика.

## 🧠 Что такое DOM и как он устроен
[[JUMP:1:59]]

DOM представляет собой модель документа, где JavaScript взаимодействует со структурой веб-страницы. Автор объясняет аббревиатуру через три составляющие:

*   **D (Document):** HTML-страница рассматривается как документ (по аналогии с файлами Word), который браузер загружает и анализирует.
*   **O (Object):** Каждый HTML-элемент (div, h1, p и т.д.) внутри DOM представлен как JavaScript-объект. Это позволяет JavaScript управлять ими, так как язык «видит» всё в виде объектов.
*   **M (Model):** HTML-код визуализируется как древовидная структура (tree structure), где корневым объектом является `window` (глобальный контекст браузера), за которым следуют `document`, `head` и `body`.

Автор отмечает, что в REST API существуют четыре базовые операции (CRUD: create, read, update, delete), и DOM полностью поддерживает их для работы с элементами HTML. Вместо того чтобы вручную создавать каждый элемент через JavaScript, разработчики используют HTML как «язык разметки-ярлыка», а браузер автоматически преобразует его в DOM-дерево.

## 🛠 Практическая работа с DOM-объектами
[[JUMP:8:26]]

Для практической работы автор использует Visual Studio Code, браузер Google Chrome и плагин **Live Server** (созданный Ritik), позволяющий мгновенно видеть изменения в коде.

### Доступ к свойствам документа

*   Объект `document` можно исследовать в консоли с помощью `console.dir(document)`.
*   Свойства, такие как `document.title`, `document.URL`, `document.domain`, `document.head` и `document.body`, позволяют считывать и даже динамически изменять содержимое страницы.
*   Автор предупреждает: хотя `document.all` визуально напоминает массив и позволяет итерироваться (благодаря `Symbol.iterator`), это на самом деле объект типа *HTMLAllCollection*, и полагаться на его индексы при манипуляциях — плохая практика, так как динамические изменения на странице сдвигают эти индексы.

## 🎯 Выбор элементов: ID, классы и теги
[[JUMP:20:58]]

Стандартные методы селекции элементов:

1.  `document.getElementById()`: возвращает ссылку на уникальный элемент по его ID.
2.  `document.getElementsByClassName()`: возвращает *HTMLCollection* (похожий на массив список) всех элементов с указанным классом.
3.  `document.getElementsByTagName()`: возвращает коллекцию элементов по имени тега.

### Современные методы: Query Selector
Автор называет `querySelector` и `querySelectorAll` наиболее мощными инструментами, так как они поддерживают CSS-селекторы:

*   `querySelector`: возвращает только ПЕРВЫЙ найденный элемент.
*   `querySelectorAll`: возвращает *NodeList*, содержащий ВСЕ найденные элементы, что позволяет использовать метод `forEach` непосредственно.
*   Использование селекторов идентично CSS: `.` для классов, `#` для ID, и поддержка псевдоклассов (например, `:nth-child(3)`).

## 🌳 Навигация и отношения в DOM-дереве
[[JUMP:42:11]]

Поскольку DOM — это дерево, элементы имеют иерархические связи (родитель/потомок/сиблинг):

*   **Downwards:** `parent.children` возвращает коллекцию дочерних элементов. Для доступа к потомкам без прохождения через все уровни можно использовать `grandparent.querySelectorAll()`.
*   **Upwards:** `element.parentElement` позволяет подняться к родителю. Метод `element.closest('.class')` ищет ближайшего предка, соответствующего селектору, двигаясь вверх по дереву.
*   **Siblings:** `element.nextElementSibling` и `element.previousElementSibling` позволяют перемещаться между элементами, находящимися на одном уровне.

## 🏗 Манипуляции: создание и изменение элементов
[[JUMP:54:47]]

Для динамического изменения страницы используются:

*   `document.createElement('tagName')`: создание нового элемента.
*   `element.className` или `element.classList.add()`: управление стилями.
*   `element.setAttribute('attr', 'value')`: установка атрибутов.
*   `container.insertBefore(newEl, targetEl)` и `container.appendChild(newEl)`: добавление элементов в DOM.

Автор подчеркивает различия между `appendChild` и `append`: последний может принимать несколько аргументов (как элементы, так и текст) и не возвращает значения, в то время как `appendChild` работает только с одним DOM-элементом и возвращает его.

## ⚡ События и формы
[[JUMP:1:05:56]]

*Event listener* — это функция, ожидающая взаимодействия пользователя (клик, набор текста и т.д.). Самый распространенный метод — `element.addEventListener('event', callback)`.

*   **Mouse events:** `click`, `dblclick`, `mousedown`, `mouseup`, `mouseenter`, `mouseleave`, `mouseover`, `mouseout`. Важное различие: `mouseenter` срабатывает один раз при входе в родителя, тогда как `mouseover` срабатывает каждый раз при наведении на любой дочерний элемент.
*   **Form events:** Для обработки отправки форм используется событие `submit`. Автор настаивает на использовании `event.preventDefault()` внутри обработчика, чтобы предотвратить стандартную перезагрузку страницы браузером.

## 🚀 Проект: Expense Tracker
[[JUMP:1:21:44]]

В финальной части видео автор пошагово создает приложение для учета расходов (CRUD-приложение). Ключевые аспекты реализации:

1.  **Разделение обязанностей:** Создана отдельная функция `updateList` для рендеринга UI и вынесены обработчики событий, что делает код чистым и поддерживаемым.
2.  **Безопасные вычисления:** Автор рекомендует хранить данные в массиве `all_transactions` объектов, а не полагаться на содержимое DOM, которое пользователь может изменить вручную.
3.  **Динамическое удаление:** Использование метода `closest('.transaction-item')` для идентификации строки и последующее использование `splice` для удаления записи из массива и `remove()` из DOM.