Поиск элементов #
Поиск в DOM — первый шаг почти любого браузерного модуля: скрипт получает ссылку на узел и дальше читает данные или вешает обработчики. Современный код опирается на CSS-селекторы через querySelector и querySelectorAll; getElementById остаётся самым быстрым способом для уникальных якорей.
getElementById #
Ищет элемент по значению атрибута id. ID должен быть уникален в документе:
const checkoutForm = document.getElementById('checkout-form')
const playlistRoot = document.getElementById('playlist-root')
Эквивалент через селектор (кавычки в ID экранируйте при необходимости):
document.querySelector('#checkout-form')
Для стабильных точек входа JSFlow (#app, #modal-host) getElementById читается явно и предсказуемо.
querySelector #
Возвращает первый элемент, подходящий под CSS-селектор, или null:
const primaryCta = document.querySelector('.checkout-bar .btn-primary')
const emptyState = document.querySelector('[data-state="empty"]')
const firstTrack = document.querySelector('.playlist .track-row')
Селектор можно уточнять контекстом — искать только внутри контейнера:
const dashboard = document.querySelector('.dashboard')
const kpiWidget = dashboard.querySelector('[data-widget="kpi"]')
const sparkline = kpiWidget.querySelector('canvas')
Так локализуется область поиска и снижается риск зацепить чужой блок на странице.
querySelectorAll #
Возвращает статический NodeList всех совпадений:
const trackRows = document.querySelectorAll('.playlist .track-row')
const metricCards = document.querySelectorAll('[data-metric]')
trackRows.length // число строк
trackRows.forEach((row) => {
row.classList.remove('is-highlighted')
})
NodeList не массив, но поддерживает forEach. Для map / filter сначала скопируйте:
const ids = [...trackRows].map((row) => row.dataset.trackId)
Сравнение методов #
| Метод | Результат | Селектор | Живая коллекция |
|---|---|---|---|
getElementById(id) | один элемент | только ID | — |
querySelector(sel) | один элемент | CSS | — |
querySelectorAll(sel) | NodeList | CSS | нет |
getElementsByClassName | HTMLCollection | класс | да |
getElementsByTagName | HTMLCollection | тег | да |
Для нового кода предпочитайте querySelector*: один синтаксис с CSS и поддержка [data-*], :not(), комбинаторов.
Практика: дашборд и checkout #
Разметка строки заказа:
<li class="cart-line" data-sku="kb-01">
<span class="cart-line__name">Клавиатура</span>
<span class="cart-line__qty">2</span>
</li>
Обновить количество по SKU:
function setLineQty(sku, qty) {
const line = document.querySelector(`.cart-line[data-sku="${sku}"]`)
if (!line) return
const qtyEl = line.querySelector('.cart-line__qty')
qtyEl.textContent = String(qty)
}
setLineQty('kb-01', 3)
Подсветить все виджеты с предупреждением:
document.querySelectorAll('.widget[data-severity="warn"]').forEach((widget) => {
widget.classList.add('widget--pulse')
})
Ошибки и null #
querySelector не бросает исключение, если ничего не найдено — проверяйте результат:
const submitBtn = document.querySelector('#checkout-form [type="submit"]')
if (!submitBtn) {
throw new Error('кнопка отправки checkout не найдена')
}
submitBtn.disabled = false
Избегайте «склеивания» селекторов из пользовательского ввода без экранирования — риск некорректного селектора или неожиданных совпадений.
Итог #
getElementById— для уникальных якорей сid.querySelector— один элемент по CSS-селектору; ищите внутри контейнера для изоляции.querySelectorAll— все совпадения; результат статический.- Всегда обрабатывайте
null, если элемент может отсутствовать в разметке.