Урок по треку Браузер и DOM 6 мин

DOM API за 6 минут

Поиск, создание и изменение узлов, живые и статичные коллекции, атрибуты и свойства.

DOM (Document Object Model) это дерево объектов, которое браузер строит из HTML. JavaScript не трогает HTML-текст: он работает с узлами этого дерева, а браузер перерисовывает страницу по изменениям.

Узлы и элементы

Узел (Node) бывает разный: элемент, текст, комментарий, сам document. Элемент (Element) это только теги. Отсюда пары свойств:

  • childNodes - все дочерние узлы, включая текст и переносы строк;
  • children - только дочерние элементы.
<ul id="list">
  <li>Один</li>
</ul>
const ul = document.getElementById('list');
ul.childNodes.length; // 3: текст "\n  ", li, текст "\n"
ul.children.length;   // 1

То же с firstChild / firstElementChild, nextSibling / nextElementSibling, parentNode / parentElement.

Поиск

  • getElementById(id) - один элемент или null.
  • querySelector(css) - первый подходящий или null.
  • querySelectorAll(css) - статичный NodeList: снимок на момент вызова.
  • getElementsByClassName, getElementsByTagName - живая HTMLCollection: сама обновляется при изменении DOM.
  • el.closest(css) - ближайший предок (включая сам элемент), подходящий под селектор. Главный помощник при делегировании событий.
  • el.matches(css) - проверка, подходит ли элемент под селектор.

Живая коллекция в цикле с удалением даёт сюрпризы: элементы сдвигаются, и каждый второй пропускается. Снимок из querySelectorAll или Array.from(...) от этого защищает.

Создание и вставка

const li = document.createElement('li');
li.textContent = 'Новый';
ul.append(li);           // в конец, принимает узлы и строки
ul.prepend('В начало');  // строка вставится как текст
li.before(other);        // перед li
li.replaceWith(x);       // заменить
li.remove();             // удалить

Если вставить узел, который уже есть в документе, он переместится, а не скопируется. Для копии есть node.cloneNode(true) (true - глубоко, с потомками; обработчики из addEventListener не копируются).

Для пачки вставок используют DocumentFragment: собрали в нём узлы, вставили один раз. Современные браузеры и так группируют изменения до следующего кадра, но фрагмент удобен и избавляет от промежуточных чтений геометрии.

textContent, innerText, innerHTML

  • textContent - весь текст узла, включая скрытый, без учёта CSS. Быстрый, безопасный: присваивание строки никогда не создаёт разметку.
  • innerText - текст «как видит пользователь»: учитывает CSS, скрытое не возвращает, при чтении вызывает пересчёт layout.
  • innerHTML - разметка. Присваивание парсит HTML: пользовательские данные туда класть нельзя, это XSS. Кроме того, перезапись innerHTML пересоздаёт всех потомков, и старые обработчики и состояние полей пропадают.

Для вставки разметки рядом есть insertAdjacentHTML('beforeend', html): не трогает существующих потомков, но так же опасна с чужими данными.

Атрибуты и свойства

Атрибут живёт в HTML, свойство в JS-объекте. Часто они синхронизированы, но не всегда:

input.getAttribute('value'); // начальное значение из разметки
input.value;                 // текущее, что ввёл пользователь

value у поля ввода: атрибут хранит значение по умолчанию, свойство текущее. href как свойство возвращает абсолютный URL, а атрибут как написано. Для data-* атрибутов есть el.dataset: data-user-id превращается в dataset.userId.

Классы: el.classList.add/remove/toggle/contains. Стили: el.style пишет только инлайн-стили, а итоговые вычисленные значения читает getComputedStyle(el).

Частые ошибки

  • Ждать, что querySelectorAll вернёт массив: это NodeList, у него есть forEach, но нет map и filter. Нужен Array.from или спред.
  • Путать children и childNodes.
  • Вставлять пользовательский ввод через innerHTML.
  • Запускать скрипт в <head> без defer и получать null от getElementById: элемента ещё нет в DOM.

Что спросят на собесе

  • Чем живая коллекция отличается от статичной, кто какую возвращает.
  • Разница textContent, innerText и innerHTML, почему innerHTML опасен.
  • Атрибут и свойство: пример, где они расходятся.
  • Как вставить много элементов эффективно.
  • Что делают closest и matches.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.