Селектор запросов JavaScript

Селектор запросов JavaScript ГИС ЖКХ

image

Содержание
  1. Основные источники
  2. Введение
  3. Миксин NonElementParentNode
  4. Миксин ParentNode
  5. Миксин NonDocumentTypeChildNode
  6. Миксин ChildNode
  7. Интерфейс Node
  8. Интерфейс Document
  9. Интерфейсы NodeIterator и TreeWalker
  10. Интерфейс Element
  11. Работа с classList
  12. Работа с атрибутами
  13. Объект Document
  14. Миксин InnerHTML
  15. Расширения интерфейса Element
  16. Заключение
  17. Базовые селекторы
  18. 1) Универсальный селектор
  19. 2) Селектор типа
  20. 3) Выбор класса
  21. 4) Селектор ID
  22. 5) Селектор атрибутов
  23. port Селекторы группировки Список селекторов будет соответствовать любому элементу с одним из селекторов в группе. images const link = document.createElement('a')
    link.className = 'my_link'
    link.href = 'https://github.com/azat-io/you-dont-know-js-ru'
    link.target = '_blank'
    link.rel = 'noopener noreferrer'
    link.textContent = 'Вы не знаете JS'
    document.body.append(link)
    log(document.links[0]) // .my_link Комбинаторы 1) комбинатор потомков Чтобы найти потомков узла, вы используете синтаксис комбинатора потомков пробела ( ): forms const form = document.createElement('form')
    form.className = 'my_form'
    document.body.append(form)
    log(document.forms[0]) // .my_form Например подойдет всем элементы внутри элемент: close() 2) Детский комбинатор write() дочерний комбинатор находит все элементы, которые являются прямыми дочерними элементами первого элемента: insertAdjacentText(where, data) Text Comment Выбрать все элементы, находящиеся непосредственно внутри элемент с классом : const text = new Text('JavaScript')
    log(text) // "JavaScript"

    const part = text.splitText

    log(part) // "Script"
    log(part.wholeText()) // Script

    const comment = new Comment('TODO')
    log(comment) // <!--TODO--> 3) Общий родственный комбинатор location log(document.location) location hash # #top 4) Соседний родственный комбинатор localhost:3000 комбинатор соседних братьев и сестер выбирает соседние братья и сестры: host localhost href protocol origin pathname links = .querySelector( host 'h1 + а' ); 3000 Псевдо protocol 1) Псевдоклассы https search псевдосопоставления элементов на основе их состояний: ? ?name=John&age=30 Например, выбирает второй элемент в списке: reload() replace() 2) Псевдоэлементы title представляют объекты, не включенные в документ. Например, соответствует первой строке всех log(document.title) // DOM элементы: head Резюме

    находит первый элемент, соответствующий селектору CSS или группе селекторов CSS. body находит все элементы, соответствующие селектору CSS или группе селекторов CSS. Селектор CSS определяет элементы, к которым применяется правило CSS. HTMLCollection const image = document.createElement('img') image.className = 'my_image' image.src = 'https://miro.medium.com/max/875/1*ZIH_wjqDfZn6NRKsDi9mvA.png' image.alt = "V8's compiler pipeline" image.width = 480 document.body.append(image) log(document.images[0]) // .my_image Было ли это руководство полезным?
  24. Документ. getElementById или просто идентификатор
  25. QuerySelectorAll
  26. QuerySelector
  27. Спички
  28. Ближайший
  29. GetElementsBy*
  30. Live collections
  31. Summary
  32. советует

Основные источники

Введение

JavaScript
предоставляет множество методов для работы с Document Object Model
или сокращенно DOM
(объектной моделью документа): одни из них являются более полезными, чем другие; одни используются часто, другие почти никогда; одни являются относительно новыми, другие признаны устаревшими.

Я постараюсь дать вам исчерпывающее представление об этих методах, а также покажу парочку полезных приемов, которые сделают вашу жизнь веб-разработчика немного легче.

Размышляя над подачей материала, я пришел к выводу, что оптимальным будет следование спецификациям с промежуточными и заключительными выводами, сопряженными с небольшими лирическими отступлениями.

Сильно погружаться в теорию мы не будем. Вместо этого, мы сосредоточимся на практической составляющей.

Для того, чтобы получить максимальную пользу от данной шпаргалки, пишите код вместе со мной и внимательно следите за тем, что происходит в консоли инструментов разработчика и на странице.

Вот как будет выглядеть наша начальная разметка:

 <ul id="list" class="list"> <li id="item1" class="item">1</li> <li id="item2" class="item">2</li> <li id="item3" class="item">3</li>
</ul> 

У нас есть список ( ul
) с тремя элементами ( li
). Список и каждый элемент имеют идентификатор ( id
) и CSS-класс ( class
). id
и class
— это атрибуты элемента. Существует множество других атрибутов: одни из них являются глобальными, т.е. могут добавляться к любому элементу, другие — локальными, т.е. могут добавляться только к определенным элементам.

Мы часто будем выводить данные в консоль, поэтому создадим такую «утилиту»:

 const log = console.log 

Миксин NonElementParentNode

Данный миксин предназначен для обработки (браузером) родительских узлов, которые не являются элементами.

В чем разница между узлами (nodes) и элементами (elements)? Если кратко, то «узлы» — это более общее понятие, чем «элементы». Узел может быть представлен элементом, текстом, комментарием и т.д. Элемент — это узел, представленный разметкой (HTML-тегами (открывающим и закрывающим) или, соответственно, одним тегом).

У рассматриваемого миксина есть метод, наследуемый от объекта Document
, с которого удобно начать разговор.

Небольшая оговорка: разумеется, мы могли бы создать список и элементы программным способом.

Для создания элементов используется метод createElement(tag)
объекта Document
:

 const listEl = document.createElement('ul') 

Такой способ создания элементов называется императивным. Он является не очень удобным и слишком многословным: создаем родительский элемент, добавляет к нему атрибуты по одному, внедряем его в DOM
, создаем первый дочерний элемент и т.д. Следует отметить, что существует и другой, более изысканный способ создания элементов — шаблонные или строковые литералы (template literals), но о них мы поговорим позже.

Одним из основных способов получения элемента (точнее, ссылки на элемент) является метод getElementById(id)
объекта Document
:

 // получаем ссылку на наш список
const listEl = document.getElementById('list')
log(listEl)
// ul#list.list - такая запись означает "элемент `ul` с `id === list`" и таким же `class` 

Почему идентификаторы должны быть уникальными в пределах приложения (страницы)? Потому что элемент с id
становится значением одноименного свойства глобального объекта window
:

 log(listEl === window.list) // true 

Как мы знаем, при обращении к свойствам и методам window
, слово window
можно опускать, например, вместо window.localStorage
можно писать просто localStorage
. Следовательно, для доступа к элементу с id
достаточно обратиться к соответствующему свойству window
:

 log(list) // ul#list.list 

Обратите внимание, что это не работает в React
и других фреймворках, абстрагирующих работу с DOM
, например, с помощью Virtual DOM
. Более того, там иногда невозможно обратиться к нативным свойствам и методам window
без window
.

Миксин ParentNode

Данный миксин предназначен для обработки родительских элементов (предков), т.е. элементов, содержащих одного и более потомка (дочерних элементов).

  • children
    — потомки элемента

 const { children } = list // list.children
log(children)
/*
HTMLCollectionimage 0: li#item1.item 1: li#item2.item 2: li#item3.item length: 3
*/ 

Такая структура называется коллекцией HTML
и представляет собой массивоподобный объект (псевдомассив). Существует еще одна похожая структура — список узлов (NodeList
)

.

Массивоподобные объекты имеют свойство length
с количеством потомков, метод forEach()
( NodeList
), позволяющий перебирать узлы (делать по ним итерацию). Такие объекты позволяют получать элементы по индексу, по названию ( HTMLCollection
) и т.д. Однако, у них отсутствуют методы настоящих массивов, такие как map()
, filter()
, reduce()
и др., что делает работу с ними не очень удобной. Поэтому массивоподобные объекты рекомендуется преобразовывать в массивы с помощью метода Array.from()
или spread-оператора:

 const children = Array.from(list.children)
// или
const children = [...list.children]
log(children) // [li#item1.item, li#item2.item, li#item3.item] - обычный массив 

  • firstElementChild
    — первый потомок — элемент
  • lastElementChild
    — последний потомок — элемент

 log(list.firstElementChild) // li#item1.item
log(list.lastElementChild) // li#item2.item 

Для дальнейших манипуляций нам потребуется периодически создавать новые элементы, поэтому создадим еще одну утилиту:

 const createEl = (id, text, tag = 'li', _class = 'item') => { const el = document.createElement(tag) el.id = id el.className = _class el.textContent = text return el
} 

Наша утилита принимает 4 аргумента: идентификатор, текст, название тега и CSS-класс. 2 аргумента (тег и класс) имеют значения по умолчанию. Функция возвращает готовый к работе элемент. Впоследствии, мы реализуем более универсальный вариант данной утилиты.

  • prepend(newNode)
    — добавляет элемент в начало списка
  • append(newNode)
    — добавляет элемент в конец списка

 // создаем новый элемент
const newItem = createEl('item0', 0)
// и добавляем его в начало списка
list.prepend(newItem)
// создаем еще один элемент
const newItem2 = createEl('item4', 4)
// и добавляем его в конец списка
list.append(newItem2)
log(children)
/*
HTMLCollectionArray.from() 0: li#item0.item 1: li#item1.item 2: li#item2.item 3: li#item3.item 4: li#item4.item
*/ 

Одной из интересных особенностей HTMLCollection
является то, что она является «живой», т.е. элементы, возвращаемые по ссылке, и их количество обновляются автоматически. Однако, эту особенность нельзя использовать, например, для автоматического добавления обработчиков событий.

  • replaceChildren(nodes)
    — заменяет потомков новыми элементами

 const newItems = [newItem, newItem2]
// заменяем потомков новыми элементами
list.replaceChildren(...newItems) // list.replaceChildren(newItem, newItem2)
log(children) // 2 

Наиболее универсальными способами получения ссылок на элементы являются методы querySelector(selector)
и querySelectorAll(selector)
. Причем, в отличие от getElementById()
, они могут вызываться на любом родительском элементе, а не только на document
. В качестве аргумента названным методам передается любой валидный CSS-селектор ( id
, class
, tag
и т.д.):

 // получаем элемент `li` с `id === item0`
const itemWithId0 = list.querySelector('#item0')
log(itemWithId0) // li#item0.item
// получаем все элементы `li` с `class === item`
const allItems = list.querySelectorAll('.item')
log(allItems) // массивоподобный объект
/*
NodeListmap() 0: li#item0.item 1: li#item4.item length: 2
*/ 

Создадим универсальную утилиту для получения элементов:

 const getEl = (selector, parent = document, single = true) => single ? parent.querySelector(selector) : [...parent.querySelectorAll(selector)] 

Наша утилита принимает 3 аргумента: CSS-селектор, родительский элемент и индикатор количества элементов (один или все). 2 аргумента (предок и индикатор) имеют значения по умолчанию. Функция возвращает либо один, либо все элементы (в виде обычного массива), совпадающие с селектором, в зависимости от значения индикатора:

 const itemWithId0 = getEl('#item0', list)
log(itemWithId0) // li#item0.item
const allItems = getEl('.item', list, false)
log(allItems) // [li#item0.item, li#item4.item] 

Миксин NonDocumentTypeChildNode

Данный миксин предназначен для обработки дочерних узлов, которые не являются документом, т.е. всех узлов, кроме document
.

  • previousElementSibling
    — предыдущий элемент
  • nextElementSibling
    — следующий элемент

 log(itemWithId0.previousElementSibling) // null
log(itemWithId0.nextElementSibling) // #item4 

Миксин ChildNode

Данный миксин предназначен для обработки дочерних элементов, т.е. элементов, являющихся потомками других элементов.

  • before(newNode)
    — вставляет новый элемент перед текущим
  • after(newNode)
    — вставляет новый элемент после текущего

 // получаем `li` с `id === item4`
const itemWithId4 = getEl('#item4', list)
// создаем новый элемент
const newItem3 = createEl('item3', 3)
// и вставляем его перед `itemWithId4`
itemWithId4.before(newItem3)
// создаем еще один элемент
const newItem4 = createEl('item2', 2)
// и вставляем его после `itemWithId0`
itemWithId0.after(newItem4) 

  • replaceWith(newNode)
    — заменяет текущий элемент новым
Про ГИС ЖКХ:  Навигация по субсидиям в России: Расширьте свои знания о вариантах финансовой поддержки

 // создаем новый элемент
const newItem5 = createEl('item1', 1)
// и заменяем им `itemWithId0`
itemWithId0.replaceWith(newItem5) 

  • remove()
    — удаляет текущий элемент

 itemWithId4.remove() 

Интерфейс Node

Данный интерфейс предназначен для обработки узлов.

  • nodeType
    — тип узла

 log(list.nodeType) // 1
// другие варианты
/* 1 -> ELEMENT_NODE (элемент) 3 -> TEXT_NODE (текст) 8 -> COMMENT_NODE (комментарий) 9 -> DOCUMENT_NODE (document) 10 -> DOCUMENT_TYPE_NODE (doctype) 11 -> DOCUMENT_FRAGMENT_NODE (фрагмент) и т.д.
*/ 

  • nodeName
    — название узла

 log(list.nodeName) // UL
// другие варианты
/* - квалифицированное название HTML-элемента прописными (заглавными) буквами - квалифицированное название атрибута - #text - #comment - #document - название doctype - #document-fragment
*/ 

  • baseURI
    — основной путь

 log(list.baseURI) // .../dom/index.html 

  • parentNode
    — родительский узел
  • parentElement
    — родительский элемент

 const itemWithId1 = getEl('#item1', list)
log(itemWithId1.parentNode) // #list
log(itemWithId1.parentElement) // #list 

  • hasChildNodes()
    — возвращает true
    , если элемент имеет хотя бы одного потомка
  • childNodes
    — дочерние узлы

 log(list.hasChildNodes()) // true
log(list.childNodes)
/*
NodeListfilter() 0: li#item1.item 1: li#item2.item 2: li#item3.item
*/ 

  • firstChild
    — первый потомок — узел
  • lastChild
    — последний потомок — узел

 log(list.firstChild) // #item1
log(list.lastChild) // #item3 

  • nextSibling
    — следующий узел
  • previousSibling
    — предыдущий узел

 log(itemWithId1.nextSibling) // #item2
log(itemWithId1.previousSibling) // null 

  • textContent
    — геттер/сеттер для извлечения/записи текста

 // получаем текст
log(itemWithId1.textContent) // 1
// меняем текст
itemWithId1.textContent = 'item1'
log(itemWithId1.textContent) // item1
// получаем текстовое содержимое всех потомков
log(list.textContent) // item123 

Для извлечения/записи текста существует еще один (устаревший) геттер/сеттер — innerText
.

  • cloneNode(deep)
    — копирует узел. Принимает логическое значение, определяющее характер копирования: поверхностное — копируется только сам узел, глубокое — копируется сам узел и все его потомки

 // создаем новый список посредством копирования существующего
const newList = list.cloneNode(false)
// удаляем у него `id` во избежание коллизий
newList.removeAttribute('id')
// меняем его текстовое содержимое
newList.textContent = 'new list'
// и вставляем его после существующего списка
list.after(newList)
// создаем еще один список
const newList2 = newList.cloneNode(true)
newList.after(newList2) 

  • isEqualNode(node)
    — сравнивает узлы
  • isSameNode(node)
    — определяет идентичность узлов

 log(newList.isEqualNode(newList2)) // true
log(newList.isSameNode(newList2)) // false 

  • contains(node)
    — возвращает true
    , если элемент содержит указанный узел

 log(list.contains(itemWithId1)) // true 

  • insertBefore(newNode, existingNode)
    — добавляет новый узел ( newNode
    ) перед существующим ( existingNode
    )

 // создаем новый элемент
const itemWithIdA = createEl('#item_a', 'a')
// и вставляем его перед `itemWithId1`
list.insertBefore(itemWithIdA, itemWithId1) 

  • appendChild(node)
    — добавляет узел в конец списка

 // создаем новый элемент
const itemWithIdC = createEl('#item_c', 'c')
// и добавляем его в конец списка
list.appendChild(itemWithIdC) 

  • replaceChild(newNode, existingNode)
    — заменяет существующий узел ( existingNode
    ) новым ( newNode
    ):

 // создаем новый элемент
const itemWithIdB = createEl('item_b', 'b')
// и заменяем им `itemWithId1`
list.replaceChild(itemWithIdB, itemWithId1) 

  • removeChild(node)
    — удаляет указанный дочерний узел

 // получаем `li` с `id === item2`
const itemWithId2 = getEl('#item2', list)
// и удаляем его
list.removeChild(itemWithId2) 

Интерфейс Document

Данный интерфейс предназначен для обработки объекта Document
.

  • URL
    и documentURI
    — адрес документа

 log(document.URL) // .../dom/index.html
log(document.documentURI) // ^ 

  • documentElement
    :

 log(document.documentElement) // html 

  • getElementsByTagName(tag)
    — возвращает все элементы с указанным тегом

 const itemsByTagName = document.getElementsByTagName('li')
log(itemsByTagName)
/*
HTMLCollection
 0: li##item_a.item 1: li#item_b.item 2: li#item3.item 3: li##item_c.item
*/ 

  • getElementsByClassName(className)
    — возвращает все элементы с указанным CSS-классом

 const itemsByClassName = list.getElementsByClassName('item')
log(itemsByClassName) // ^ 

  • createDocumentFragment()
    — возвращает фрагмент документа:

 // создаем фрагмент
const fragment = document.createDocumentFragment()
// создаем новый элемент
const itemWithIdD = createEl('item_d', 'd')
// добавляем элемент во фрагмент
fragment.append(itemWithIdD)
// добавляем фрагмент в список
list.append(fragment) 

Фрагменты позволяют избежать создания лишних элементов. Они часто используются при работе с разметкой, скрытой от пользователя с помощью тега template
(метод cloneNode()
возвращает DocumentFragment
).

  • createTextNode(data)
    — создает текст

  • importNode(existingNode, deep)
    — создает новый узел на основе существующего

 // создаем новый список на основе существующего
const newList3 = document.importNode(list, true)
// вставляем его перед существующим списком
list.before(newList3)
// и удаляем во избежание коллизий
newList3.remove() 

  • createAttribute(attr)
    — создает указанный атрибут

Интерфейсы NodeIterator и TreeWalker

Интерфейсы NodeIterator

и TreeWalker

предназначены для обхода (traverse) деревьев узлов. Я не сталкивался с примерами их практического использования, поэтому ограничусь парочкой примеров:

 // createNodeIterator(root, referenceNode, pointerBeforeReferenceNode, whatToShow, filter)
const iterator = document.createNodeIterator(list)
log(iterator)
log(iterator.nextNode()) // #list
log(iterator.nextNode()) // #item_a
log(iterator.previousNode()) // #item_a
log(iterator.previousNode()) // #list
log(iterator.previousNode()) // null
// createTreeWalker(root, whatToShow, filter)
// применяем фильтры - https://dom.spec.whatwg.org/#interface-nodefilter
const walker = document.createTreeWalker(list, '0x1', { acceptNode: () => 1 })
log(walker)
log(walker.parentNode()) // null
log(walker.firstChild()) // #item_a
log(walker.lastChild()) // null
log(walker.previousSibling()) // null
log(walker.nextSibling()) // #item_b
log(walker.nextNode()) // #item3
log(walker.previousNode()) // #item_b 

Интерфейс Element

Данный интерфейс предназначен для обработки элементов.

  • localName
    и tagName
    — название тега

 log(list.localName) // ul
log(list.tagName) // UL 

  • id
    — геттер/сеттер для идентификатора
  • className
    — геттер/сеттер для CSS-класса

 log(list.id) // list
list.id = 'LIST'
log(LIST.className) // list 

  • classList
    — все CSS-классы элемента (объект DOMTokenList
    )

 const button = createEl('button', 'Click me', 'my_button', 'btn btn-primary')
log(button.classList)
/*
DOMTokenList 0: "btn" 1: "btn-primary" length: 2 value: "btn btn-primary"
*/ 

Работа с classList

  • classList.add(newClass)
    — добавляет новый класс к существующим
  • classList.remove(existingClass)
    — удаляет указанный класс
  • classList.toggle(className, force?)
    — удаляет существующий класс или добавляет новый. Если опциональный аргумент force
    имеет значение true
    , данный метод только добавляет новый класс при отсутствии, но не удаляет существующий класс (в этом случае toggle() === add()
    ). Если force
    имеет значение false
    , данный метод только удаляет существующий класс при наличии, но не добавляет отсутствующий класс (в этом случае toggle() === remove()
    )
  • classList.replace(existingClass, newClass)
    — заменяет существующий класс ( existingClass
    ) на новый ( newClass
    )
  • classList.contains(className)
    — возвращает true
    , если указанный класс обнаружен в списке классов элемента (данный метод идентичен className.includes(className)
    )

 // добавляем к кнопке новый класс
button.classList.add('btn-lg')
// удаляем существующий класс
button.classList.remove('btn-primary')
// у кнопки есть класс `btn-lg`, поэтому он удаляется
button.classList.toggle('btn-lg')
// заменяем существующий класс на новый
button.classList.replace('btn', 'btn-success')
log(button.className) // btn-success
log(button.classList.contains('btn')) // false
log(button.className.includes('btn-success')) // true 

Работа с атрибутами

  • hasAttributes()
    — возвращает true
    , если у элемента имеются какие-либо атрибуты
  • getAttributesNames()
    — возвращает названия атрибутов элемента
  • getAttribute(attrName)
    — возвращает значение указанного атрибута
  • setAttribute(name, value)
    — добавляет указанные атрибут и его значение к элементу
  • removeAttribute(attrName)
    — удаляет указанный атрибут
  • hasAttribute(attrName)
    — возвращает true
    при наличии у элемента указанного атрибута
  • toggleAttribute(name, force)
    — добавляет новый атрибут при отсутствии или удаляет существующий атрибут. Аргумент force
    аналогичен одноименному атрибуту classList.toggle()

 log(button.hasAttributes()) // true
log(button.getAttributeNames()) // ['id', 'class']
log(button.getAttribute('id')) // button
button.setAttribute('type', 'button')
button.removeAttribute('class')
log(button.hasAttribute('class')) // false 

В использовании перечисленных методов для работы с атрибутами нет особой необходимости, поскольку многие атрибуты являются геттерами/сеттерами, т.е. позволяют извлекать/записывать значения напрямую. Единственным исключением является метод removeAttribute()
, поскольку существуют атрибуты без значений: например, если кнопка имеет атрибут disabled
, установка значения данного атрибута в false
не приведет к снятию блокировки — для этого нужно полностью удалить атрибут disabled
с помощью removeAttribute()
.

Отдельного упоминания заслуживает атрибут data-*
, где символ *
означает любую строку. Он предназначен для определения пользовательских атрибутов. Например, в нашей начальной разметке для уникальной идентификации элементов используется атрибут id
. Однако, это приводит к загрязнению глобального пространства имен, что чревато коллизиями между нашими переменными и, например, переменными используемой нами библиотеки — когда какой-либо объект библиотеки пытается записаться в свойство window
, которое уже занято нашим id
.

Название data-атрибута после символа -
становится одноименным свойством объекта dataset
. Например, значение атрибута data-id
можно получить через свойство dataset.id
.

  • closest(selectors)
    — возвращает первый родительский элемент, совпавший с селекторами

 LIST.append(button)
log(button.closest('#LIST', 'document.body')) // #LIST 

  • matches(selectors)
    — возвращает true
    , если элемент совпадает хотя бы с одним селектором

 log(button.matches('.btn', '[type="button"]'))
// у кнопки нет класса `btn`, но есть атрибут `type` со значением `button`,
// поэтому возвращается `true` 

  • insertAdjacentElement(where, newElement)
    — универсальный метод для вставки новых элементов перед/в начало/в конец/после текущего элемента. Аргумент where
    определяет место вставки. Возможные значения:

    • beforebegin
      — перед открывающим тегом
    • afterbegin
      — после открывающего тега
    • beforeend
      — перед закрывающим тегом
    • afterend
      — после закрывающего тега

  • insertAdjacentText(where, data)
    — универсальный метод для вставки текста

  • Text
    — конструктор для создания текста

  • Comment
    — конструктор для создания комментария

 const text = new Text('JavaScript')
log(text) // "JavaScript"
const part = text.splitTextonlog(part) // "Script"
log(part.wholeText()) // Script
const comment = new Comment('TODO')
log(comment) // <!--TODO--> 

Объект Document

  • location
    — объект с информацией о текущей локации документа

 log(document.location) 

Свойства объекта location
:

  • hash
    — хэш-часть URL (символ #
    и все, что следует за ним), например, #top
  • host
    — название хоста и порт, например, localhost:3000
  • hostname
    — название хоста, например, localhost
  • href
    — полный путь
  • origin
    protocol
    + host
  • pathname
    — путь без протокола
  • port
    — порт, например, 3000
  • protocol
    — протокол, например, https
  • search
    — строка запроса (символ ?
    и все, что следует за ним), например, ?name=John&age=30

  • reload()
    — перезагружает текущую локацию

  • replace()
    — заменяет текущую локацию на новую

  • title
    — заголовок документа

 log(document.title) // DOM 

  • head
    — метаданные документа

  • body
    — тело документа

  • images
    — псевдомассив ( HTMLCollection
    ), содержащий все изображения, имеющиеся в документе

 const image = document.createElement('img')
image.className = 'my_image'
image.src = 'https://miro.medium.com/max/875/1*ZIH_wjqDfZn6NRKsDi9mvA.png'
image.alt = "V8's compiler pipeline"
image.width = 480
document.body.append(image)
log(document.images[0]) // .my_image 

  • links
    — псевдомассив, содержащий все ссылки, имеющиеся в документе

 const link = document.createElement('a')
link.className = 'my_link'
link.href = 'https://github.com/azat-io/you-dont-know-js-ru'
link.target = '_blank'
link.rel = 'noopener noreferrer'
link.textContent = 'Вы не знаете JS'
document.body.append(link)
log(document.links[0]) // .my_link 

  • forms
    — псевдомассив, содержащий все формы, имеющиеся в документе

 const form = document.createElement('form')
form.className = 'my_form'
document.body.append(form)
log(document.forms[0]) // .my_form 

Следующие методы и свойство считаются устаревшими:

  • open()
    — открывает документ для записи. При этом документ полностью очищается
  • close()
    — закрывает документ для записи
  • write()
    — записывает данные (текст, разметку) в документ
  • writeln()
    — записывает данные в документ с переносом на новую строку
  • designMode
    — управление режимом редактирования документа. Возможные значения: on
    и off
    . Наберите document.designMode = 'on'
    в консоли DevTools
    и нажмите Enter
    . Вуаля, страница стала редактируемой: можно удалять/добавлять текст, перетаскивать изображения и т.д.
  • execCommand()
    — выполняет переданные команды. Со списоком доступных команд можно ознакомиться здесь
    . Раньше этот метод активно использовался для записи/извлечения данных из буфера обмена (команды copy
    и paste
    ). Сейчас для этого используются методы navigator.clipboard.writeText()
    , navigator.clipboard.readText()
    и др.

Миксин InnerHTML

Геттер/сеттер innerHTML
позволяет извлекать/записывать разметку в элемент. Для подготовки разметки удобно пользоваться шаблонными литералами:

 const itemsTemplate = ` <li data-id="item1" class="item">1</li> <li data-id="item2" class="item">2</li> <li data-id="item3" class="item">3</li>
`
LIST.innerHTML = itemsTemplate
log(LIST.innerHTML)
/*
<li data-id="item1" class="item">1</li>
<li data-id="item2" class="item">2</li>
<li data-id="item3" class="item">3</li>
*/ 

Расширения интерфейса Element

  • outerHTML
    — геттер/сеттер для извлечения/записи внешней разметки элемента: то, что возвращает innerHTML
    + разметка самого элемента

 log(LIST.outerHTML)
/*
<ul id="LIST" class="list"> <li data-id="item1" class="item">1</li> <li data-id="item2" class="item">2</li> <li data-id="item3" class="item">3</li>
</ul>
*/ 

  • insertAdjacentHTML(where, string)
    — универсальный метод для вставки разметки в виде строки. Аргумент where
    аналогичен одноименному аргументу метода insertAdjacentElement()

Метод insertAdjacentHTML()
в сочетании с шаблонными литералами и их продвинутой версией — тегированными шаблонными литералами (tagged template literals) предоставляет много интересных возможностей по манипулированию разметкой документа. По сути, данный метод представляет собой движок шаблонов (template engine) на стороне клиента, похожий на Pug
, Handlebars
и др. серверные движки. С его помощью (при участии History API
) можно, например, реализовать полноценное одностраничное приложение ( Single Page Application
или сокращенно SPA
). Разумеется, для этого придется написать чуть больше кода, чем при использовании какого-либо фронтенд-фреймворка.

Вот несколько полезных ссылок, с которых можно начать изучение этих замечательных инструментов:

Иногда требуется создать элемент на основе шаблонной строки. Как это можно сделать? Вот соответствующая утилита:

 const createElFromStr = (str) => { // создаем временный элемент const el = document.createElement('div') // записываем в него переданную строку - разметку el.innerHTML = str // извлекаем наш элемент // если мы используем здесь метод `firstChild()`, может вернуться `#text` // одна из проблем шаблонных строк заключается в большом количестве лишних пробелов const child = el.fisrtElementChild // удаляем временный элемент el.remove() // и возвращаем наш элемент return child
}
// шаблон списка
const listTemplate = `
<ul id="list"> <li data-id="item1" class="item">1</li> <li data-id="item2" class="item">2</li> <li data-id="item3" class="item">3</li>
</ul>
`
// создаем список на основе шаблона
const listEl = createElFromStr(listTemplate)
// и вставляем его в тело документа
document.body.append(listEl) 

Существует более экзотический способ создания элемента на основе шаблонной строки. Он предполагает использование конструктора DOMParser()

:

 const createElFromStr = (str) => { // создаем новый парсер const parser = new DOMParser() // парсер возвращает новый документ const { body: { children } } = parser.parseFromString(str, 'text/html') // нас интересует первый дочерний элемент тела нового документа return children[0]
}
const listTemplate = `
<ul id="list"> <li data-id="item1" class="item">1</li> <li data-id="item2" class="item">2</li> <li data-id="item3" class="item">3</li>
</ul>
`
const listEl = createElFromStr(listTemplate)
document.body.append(listEl) 

Еще более экзотический, но при этом самый короткий способ предполагает использование расширения для объекта Range

— метода createContextualFragment()
:

 const createElFromStr = (str) => { // создаем новый диапазон const range = new Range() // создаем фрагмент const fragment = range.createContextualFragment(str) // и возвращаем его return fragment
}
// или в одну строку
const createFragment = (str) => new Range().createContextualFragment(str)
const listTemplate = `
<ul id="list"> <li data-id="item1" class="item">1</li> <li data-id="item2" class="item">2</li> <li data-id="item3" class="item">3</li>
</ul>
`
document.body.append(createFragment(listTemplate)) 

В завершение, как и обещал, универсальная утилита для создания элементов:

 // функция принимает название тега и объект с настройками
const createEl = (tag, opts) => { const el = document.createElement(tag) // перебираем ключи объекта и записывает соответствующие свойства в элемент for (const key in opts) { el[key] = opts[key] } // возвращаем готовый элемент return el
}
const button = createEl('button', { // настройками могут быть атрибуты id: 'my_button', className: 'btn btn-primary', textContent: 'Click me', title: 'My button', autofocus: true, // стили style: 'color: red; cursor: pointer;', // обработчики и т.д. onmouseenter: function () { this.style.color = 'green' }, onmouseout: function () { this.style.color = 'blue' }, onclick: () => alert('Привет!')
})
document.body.append(button) 

Заключение

Современный JS
предоставляет богатый арсенал методов для работы с DOM
. Данных методов вполне достаточно для решения всего спектра задач, возникающих при разработке веб-приложений. Хорошее знание этих методов, а также умение их правильно применять гарантируют не только высокое качество (чистоту) кода, но также избавляют от необходимости использовать DOM-библиотеки (такие как jQuery
), что в совокупности обусловливает производительность приложения, его поддерживаемость и масштабируемость.

Разумеется, шпаргалка — это всего лишь карманный справочник, памятка для быстрого восстановления забытого материала, предполагающая наличие определенного багажа знаний.


VDS
от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Селектор запросов JavaScript

Summary forms
: in this tutorial, you will learn how to use the JavaScript

and

to find elements based on CSS selectors.

Introduction to JavaScript querySelector() and querySelectorAll() methods

    The

    is a method of the

    interface. The

     method allows you to select the first element that matches one or more CSS selectors. 
    • const form = document.createElement('form')
      form.className = 'my_form'
      document.body.append(form)
      log(document.forms[0]) // .my_form

    • In this syntax, the
    • is a CSS selector or a group of CSS selectors to match the descendant elements of the
    • . open()
      close() If the

      is not valid CSS syntax, the method will raise a write()
      exception.

    • If no element matches the CSS selectors, the
    • returns links
      .
    • The

       method is available on the 

      object or any const link = document.createElement('a')
      link.className = 'my_link'
      link.href = 'https://github.com/azat-io/you-dont-know-js-ru'
      link.target = '_blank'
      link.rel = 'noopener noreferrer'
      link.textContent = 'Вы не знаете JS'
      document.body.append(link)
      log(document.links[0]) // .my_link

      object.

      Кроме querySelector()
      , вы можете использовать querySelectorAll()
      метод для выбора всех элементов, соответствующих селектору CSS или группе селекторов CSS:

         elementList = parentNode.querySelectorAll(selector);    

      querySelectorAll()
      метод возвращает статический NodeList
      элементов, соответствующих селектору CSS. Если ни один элемент не соответствует, возвращается пустой NodeList
      .

      Преобразовать NodeList
      к массиву вы используете Array.from()
      такой метод:

         nodeList = .querySelectorAll(selector); elements = .from(nodeList);    

      Базовые селекторы

         

      1) Универсальный селектор

      Универсальный селектор обозначается *
      который соответствует всем элементам любого типа:

       
         element = .querySelector();    

      И это выделяет все элементы в документе:

         elements = .querySelectorAll();    

      2) Селектор типа

      Чтобы выбрать элементы по имени узла, вы используете селектор типа, например, a
      выбирает все <a>
      элементы:

       
         firstHeading = .querySelector();    
         heading2 = .querySelectorAll();    

      3) Выбор класса

      Чтобы найти элемент с заданным классом CSS, вы используете синтаксис селектора класса:

         
         note = .querySelector();    
         notes = .querySelectorAll();    

      4) Селектор ID

      Чтобы выбрать элемент на основе значения его идентификатора, вы используете синтаксис селектора идентификатора:

         
         logo = .querySelector();    

      Начиная с id
      должен быть уникальным в документе, querySelectorAll()
      не актуально.

      5) Селектор атрибутов

        hostname JSON / JSON с комментариями links  

      open()

       port Селекторы группировки 

       
      Список селекторов будет соответствовать любому элементу с одним из селекторов в группе. images

     

    const link = document.createElement('a')
    link.className = 'my_link'
    link.href = 'https://github.com/azat-io/you-dont-know-js-ru'
    link.target = '_blank'
    link.rel = 'noopener noreferrer'
    link.textContent = 'Вы не знаете JS'
    document.body.append(link)
    log(document.links[0]) // .my_link


  • Комбинаторы

      1) комбинатор потомков

    • Чтобы найти потомков узла, вы используете синтаксис комбинатора потомков пробела ( ): forms

       

      const form = document.createElement('form')
      form.className = 'my_form'
      document.body.append(form)
      log(document.forms[0]) // .my_form
      Например

      подойдет всем
      элементы внутри

        элемент:
    • close()
    • 2) Детский комбинатор write()

    • дочерний комбинатор находит все элементы, которые являются прямыми дочерними элементами первого элемента:

    • insertAdjacentText(where, data)

      Text

    • Comment Выбрать все
      элементы, находящиеся непосредственно внутри

       элемент с классом 

      :
      const text = new Text('JavaScript')
      log(text) // "JavaScript"

      const part = text.splitText

      log(part) // "Script"
      log(part.wholeText()) // Script

      const comment = new Comment('TODO')
      log(comment) // <!--TODO-->

      • 3) Общий родственный комбинатор location

        log(document.location)

        location

        hash #

        #top 4) Соседний родственный комбинатор

      • localhost:3000
        комбинатор соседних братьев и сестер выбирает соседние братья и сестры: host

      • localhost
      • href

        protocol
        origin
        pathname

      •  links = .querySelector( host 'h1 + а' 
      • );
      • 3000
      • Псевдо
      • protocol 1) Псевдоклассы https

      • search
        псевдосопоставления элементов на основе их состояний:
      • ?

          ?name=John&age=30

        • Например,

          выбирает второй

          элемент в списке:

        • reload()

        • replace()

        • 2) Псевдоэлементы
        • title
          представляют объекты, не включенные в документ.

          Например,
          соответствует первой строке всех log(document.title) // DOM
          элементы:

          • head Резюме
          • находит первый элемент, соответствующий селектору CSS или группе селекторов CSS. body

          • находит все элементы, соответствующие селектору CSS или группе селекторов CSS.

          • Селектор CSS определяет элементы, к которым применяется правило CSS. HTMLCollection

             const image = document.createElement('img')
            image.className = 'my_image'
            image.src = 'https://miro.medium.com/max/875/1*ZIH_wjqDfZn6NRKsDi9mvA.png'
            image.alt = "V8's compiler pipeline"
            image.width = 480
            document.body.append(image)
            log(document.images[0]) // .my_image Было ли это руководство полезным? 

          • Навигационные свойства DOM хороши, когда элементы расположены близко друг к другу. Что, если это не так? Как получить произвольный элемент страницы?

            Для этого есть дополнительные методы поиска.

            Документ. getElementById или просто идентификатор

            Если элемент имеет id
            атрибут, мы можем получить элемент, используя метод document.getElementById(id)
            , неважно где.

             <div id="elem"> <div id="elem-content">Element</div>
            </div>
            <script> // get the element let elem = document.getElementById('elem'); // make its background red elem.style.background = 'red';
            </script> 

            Кроме того, есть глобальная переменная с именем id
            который ссылается на элемент:

             <div id="elem"> <div id="elem-content">Element</div>
            </div>
            <script> // elem is a reference to DOM-element with id="elem" elem.style.background = 'red'; // id="elem-content" has a hyphen inside, so it can't be a variable name // ...but we can access it using square brackets: window['elem-content']
            </script> 
             <div id="elem"></div>
            <script> let elem = 5; // now elem is 5, not a reference to <div id="elem"> alert(elem); // 5
            </script> 

            Пожалуйста, не используйте глобальные переменные с идентификатором для доступа к элементам

            Это поведение описано в спецификации
            , но поддерживается в основном для совместимости.

            Браузер пытается нам помочь, смешивая пространства имён JS и DOM. Это нормально для простых скриптов, встроенных в HTML, но в целом это не очень хорошо. Возможны конфликты имен. Кроме того, когда кто-то читает код JS и не видит HTML, непонятно, откуда берется переменная.

            Здесь в уроке мы используем id
            для прямой ссылки на элемент для краткости, когда очевидно, откуда этот элемент.

            В реальной жизни document.getElementById
            является предпочтительным методом.

            id
            должен быть уникальным

            id
            Должно быть уникальным. В документе может быть только один элемент с данным id
            .

            Если есть несколько элементов с одним и тем же id
            , то поведение методов, которые его используют, непредсказуемо, например. document.getElementById
            может возвращать любой из таких элементов случайным образом. Поэтому, пожалуйста, придерживайтесь правила и сохраняйте id
            уникальный.

            Только document.getElementById
            , не anyElem.getElementById

            Метод getElementById
            можно вызывать только на document
            объект. Ищет данное id
            во всем документе.

            QuerySelectorAll

            Безусловно, самый универсальный метод, elem.querySelectorAll(css)
            возвращает все элементы внутри elem
            соответствующий заданному селектору CSS.

            Здесь ищем всех <li>
            элементы, которые являются последними детьми:

             <ul> <li>The</li> <li>test</li>
            </ul>
            <ul> <li>has</li> <li>passed</li>
            </ul>
            <script> let elements = document.querySelectorAll('ul > li:last-child'); for (let elem of elements) { alert(elem.innerHTML); // "test", "passed" }
            </script> 

            Этот метод действительно мощный, потому что можно использовать любой селектор CSS.

            Также может использовать псевдоклассы

            Псевдоклассы в селекторе CSS, такие как :hover
            и :active
            также поддерживаются. Например, document.querySelectorAll(':hover')
            вернет коллекцию с элементами, над которыми указатель сейчас закончился (в порядке вложения: от самого внешнего <html>
            к самому вложенному).

            QuerySelector

            Призыв к elem.querySelector(css)
            возвращает первый элемент для данного селектора CSS.

            Спички

            Предыдущие методы выполняли поиск в DOM.

            elem.matches(css)
            ничего не ищет, а просто проверяет elem
            соответствует заданному CSS-селектору. Он возвращается true
            или false
            .

            Этот метод удобен, когда мы перебираем элементы (например, в массиве или что-то в этом роде) и пытаемся отфильтровать те, которые нас интересуют.

             <a href="http://example.com/file.zip">...</a>
            <a href="http://ya.ru">...</a>
            <script> // can be any collection instead of document.body.children for (let elem of document.body.children) { if (elem.matches('a[href$="zip"]')) { alert("The archive reference: " + elem.href ); } }
            </script> 

            Ближайший

            Предки
            элемента: родитель, родитель родителя, его родитель и так далее. Предки вместе образуют цепочку родителей от элемента к вершине.

            Метод elem.closest(css)
            ищет ближайшего предка, который соответствует селектору CSS. elem
            сам тоже включается в поиск.

            Другими словами, метод closest
            поднимается от элемента и проверяет каждого из родителей. Если он соответствует селектору, то поиск останавливается и возвращается предок.

             <h1>Contents</h1>
            <div class="contents"> <ul class="book"> <li class="chapter">Chapter 1</li> <li class="chapter">Chapter 2</li> </ul>
            </div>
            <script> let chapter = document.querySelector('.chapter'); // LI alert(chapter.closest('.book')); // UL alert(chapter.closest('.contents')); // DIV alert(chapter.closest('h1')); // null (because h1 is not an ancestor)
            </script> 

            GetElementsBy*

            Существуют и другие способы поиска узлов по тегу, классу и т.д.

            Сегодня они в основном уже история, так как querySelector
            мощнее и короче для записи.

            Итак, здесь мы рассмотрим их в основном для полноты картины, хотя вы все еще можете найти их в старых сценариях.

            • elem.getElementsByTagName(tag)
              ищет элементы с заданным тегом и возвращает их коллекцию. tag
              параметр также может быть звездочкой "*"
              для «любых тегов».
            • elem.getElementsByClassName(className)
              возвращает элементы, имеющие заданный класс CSS.
            • document.getElementsByName(name)
              возвращает элементы с заданным name
              атрибут, для всего документа. Используется очень редко.
             // get all divs in the document
            let divs = document.getElementsByTagName('div'); 

            Найдем все input
            теги внутри таблицы:

             <table id="table"> <tr> <td>Your age:</td> <td> <label> <input type="radio" name="age" value="young" checked> less than 18 </label> <label> <input type="radio" name="age" value="mature"> from 18 to 50 </label> <label> <input type="radio" name="age" value="senior"> more than 60 </label> </td> </tr>
            </table>
            <script> let inputs = table.getElementsByTagName('input'); for (let input of inputs) { alert( input.value + ': ' + input.checked ); }
            </script> 

            Не забудьте "s"
            письмо!

            Начинающие разработчики иногда забывают букву "s"
            . То есть пытаются дозвониться

            вместо

          • .

            The "s"
            letter is absent in getElementById
            , because it returns a single element. But getElementsByTagName
            returns a collection of elements, so there’s "s"
            inside.

            It returns a collection, not an element!

            Another widespread novice mistake is to write:

             // doesn't work
            document.getElementsByTagName('input').value = 5; 

            That won’t work, because it takes a collection
            of inputs and assigns the value to it rather than to elements inside it.

            We should either iterate over the collection or get an element by its index, and then assign, like this:

             // should work (if there's an input)
            document.getElementsByTagName('input')[0].value = 5; 

            Looking for .article
            elements:

             <form name="my-form"> <div class="article">Article</div> <div class="long article">Long article</div>
            </form>
            <script> // find by name attribute let form = document.getElementsByName('my-form')[0]; // find by class inside the form let articles = form.getElementsByClassName('article'); alert(articles.length); // 2, found two elements with class "article"
            </script> 

            Live collections

            All methods "getElementsBy*"
            return a live
            collection. Such collections always reflect the current state of the document and “auto-update” when it changes.

            In the example below, there are two scripts.

            1. The first one creates a reference to the collection of <div>
              . As of now, its length is 1
              .
            2. The second scripts runs after the browser meets one more <div>
              , so its length is 2
              .
             <div>First div</div>
            <script> let divs = document.getElementsByTagName('div'); alert(divs.length); // 1
            </script>
            <div>Second div</div>
            <script> alert(divs.length); // 2
            </script> 

            In contrast, querySelectorAll
            returns a static
            collection. It’s like a fixed array of elements.

            If we use it instead, then both scripts output 1
            :

             <div>First div</div>
            <script> let divs = document.querySelectorAll('div'); alert(divs.length); // 1
            </script>
            <div>Second div</div>
            <script> alert(divs.length); // 1
            </script> 

            Now we can easily see the difference. The static collection did not increase after the appearance of a new div
            in the document.

            Summary

            There are 6 main methods to search for nodes in DOM:

            By far the most used are querySelector
            and querySelectorAll
            , but getElement(s)By*
            can be sporadically helpful or found in the old scripts.

            • There is elem.matches(css)
              to check if elem
              matches the given CSS selector.
            • There is elem.closest(css)
              to look for the nearest ancestor that matches the given CSS-selector. The elem
              itself is also checked.

            And let’s mention one more method here to check for the child-parent relationship, as it’s sometimes useful:

            • elemA.contains(elemB)
              returns true if elemB
              is inside elemA
              (a descendant of elemA
              ) or when elemA==elemB
              .

            Метод определён для объекта document
            и любого HTML-элемента ( Element

            ) страницы. Позволяет найти элемент по CSS-селектору среди дочерних. Если элементов несколько, то вернётся первый подходящий. Если подходящих элементов нет, то вернёт null

            .

            Метод принимает один параметр — CSS-селектор
            в виде строки. Если передан не CSS-селектор, то система выбросит ошибку. Например, можно выбрать первый элемент внутри <div>

            :

                                                                         Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. Быть энтузиасткой сделалось её общественным положением, и иногда, когда ей даже того не хотелось, она, чтобы не обмануть ожиданий людей, знавших её, делалась энтузиасткой. Сдержанная улыбка, игравшая постоянно на лице Анны Павловны, хотя и не шла к её отжившим чертам, выражала, как у избалованных детей, постоянное сознание своего милого недостатка, от которого она не хочет, не может и не находит нужным исправляться. <p>Это параграф, дочерний для body</p> const firstParagraph = document.querySelector('div > p') // напечатает текст, начинающийся с 'Князь Василий' // ищем несуществующий элемент const spanFromBody = document.querySelector('span')  Князь Василий говорил всегда лениво, как актер говорит роль старой пиесы. Анна Павловна Шерер, напротив, несмотря на свои сорок лет, была преисполнена оживления и порывов. Быть энтузиасткой сделалось её общественным положением, и иногда, когда ей даже того не хотелось, она, чтобы не обмануть ожиданий людей, знавших её, делалась энтузиасткой. Сдержанная улыбка, игравшая постоянно на лице Анны Павловны, хотя и не шла к её отжившим чертам, выражала, как у избалованных детей, постоянное сознание своего милого недостатка, от которого она не хочет, не может и не находит нужным исправляться. Это параграф, дочерний для body  firstParagraph 'div > p' firstParagraph // напечатает текст, начинающийся с 'Князь Василий' // ищем несуществующий элемент spanFromBody spanFromBody     

            Динамический пример, введите селектор в поле поиска и нажмите «Искать»:

          • Открыть демо в новой вкладке
          • links

              Метод работает с open() DOM

            • , который связан с HTML-разметкой. Каждый HTML-элемент имеет родительские и дочерние элементы:
          • Родители — это элементы, которые содержат текущий элемент. В примере выше у первого элемента write()
          • есть два родительских элемента —

             const image = document.createElement('img')
            image.className = 'my_image'
            image.src = 'https://miro.medium.com/max/875/1*ZIH_wjqDfZn6NRKsDi9mvA.png'
            image.alt = "V8's compiler pipeline"
            image.width = 480
            document.body.append(image)
            log(document.images[0]) // .my_image 

            и

            .
          • Дочерние элементы — это элементы, которые содержит текущий элемент. Они могут быть, а могут не быть. Например, для тега

            все элементы страницы дочерние. У

             дочерний элемент — текст внутри тега. 
          • close()

          Если вы работаете с корнем страницы, объектом

          , то поиск идёт по всем элементам страницы (от

            ), если от конкретного элемента, то поиск идёт только по всем дочерним. const link = document.createElement('a')
            link.className = 'my_link'
            link.href = 'https://github.com/azat-io/you-dont-know-js-ru'
            link.target = '_blank'
            link.rel = 'noopener noreferrer'
            link.textContent = 'Вы не знаете JS'
            document.body.append(link)
            log(document.links[0]) // .my_link
        • forms
           советует 


          const form = document.createElement('form')
          form.className = 'my_form'
          document.body.append(form)
          log(document.forms[0]) // .my_form

          🛠 Для поиска первого элемента в DOM нужно передать строку

          аргументом

          , её называют

        • wildcard
        • .

          Метод определён для объекта document
          и любого HTML-элемента ( Element

          ) страницы. Позволяет найти все элементы с заданным классом
          или классами среди дочерних.

          Метод принимает один параметр — название класса или список классов в виде строки. Если передаёшь список классов, то раздели их названия пробелами class1 class2
          . Элемент подходит, если у него есть все классы из перечисленных.

          Возвращает похожую на массив HTML
          Collection
          с найденными элементами. Если элементов не нашлось, то коллекция будет пустая, то есть с размером 0.

                                                                                <div class="paragraph subtitle">Div с классом paragraph и subtitle</div>   <p class="paragraph">Параграф с классом paragraph</p>   const paragraphs = document.getElementsByClassName('paragraph')   // напечатает 2     const divEl = document.getElementById('title')   // ищем параграфы внутри div:   const paragraphsFromDiv = divEl.getElementsByClassName('paragraph')   // напечатает 1, так как внутри div только один элемент с классом paragraph     const subtitleParagraphs = document.getElementsByClassName(   // напечатает 1, так как на странице только один элемент,   // у которого есть и класс paragraph, и класс subtitle     // ищем несуществующий элемент   const spanFromBody = document.getElementsByClassName('hello')   console.log(spanFromBody.length) // напечатает 0    Привет, незнакомец!  
          Div с классом paragraph и subtitle Параграф с классом paragraph  paragraphs paragraphs  // напечатает 2  divEl  // ищем параграфы внутри div:  paragraphsFromDiv divEl paragraphsFromDiv  // напечатает 1, так как внутри div только один элемент с классом paragraph  subtitleParagraphs subtitleParagraphs  // напечатает 1, так как на странице только один элемент,   // у которого есть и класс paragraph, и класс subtitle   // ищем несуществующий элемент  spanFromBody spanFromBody  // напечатает 0       

          Метод работает с DOM
          , который связан с HTML-разметкой. Каждый HTML-элемент имеет родительские и дочерние элементы:

          • Родительские элементы — это элементы, внутри которых находится элемент. В примере выше у элемента <h1>
            есть два родительских элемента — <div>
            и <body>
            .
          • Дочерние элементы — это элементы, которые содержит текущий элемент. Они могут быть, а могут не быть. Например, для тега <body>
            все элементы страницы дочерние. У <h1>
            дочерний элемент — текст внутри тега.

          Если работаешь с корнем страницы, объектом document
          , то поиск идёт по всем элементам страницы (т.е. от <body>
          ), если от конкретного элемента, то поиск идёт только по всем дочерним.

          Так как мы заранее не знаем, сколько элементов с искомым тегом найдётся, то метод возвращает коллекцию элементов.

          Каждый элемент HTML может иметь класс или несколько классов. Когда пользуетесь get
          Elements
          By
          Class
          Name
          (

          )
          , поиск идёт только по классам (атрибут class
          ). Названия тегов и все остальные атрибуты игнорируются.

          советует

          🛠 Метод возвращает живую коллекцию. Это означает, что коллекция будет автоматически обновляться, если на странице появятся подходящие элементы. Если не очень понятно, как это работает, то посмотрите пример в статье по методу get
          Elements
          By
          Tag
          Name
          (

          )
          .

          🛠 Нужно быть осторожным, когда пишете циклы над HTMLCollection
          . Так как коллекция живая, то цикл может стать бесконечным в тех случаях, когда на страницу добавляются и удаляются подходящие под поиск элементы.

          🛠 Скрипты, которые работают с HTML видят только ту разметку, которую уже распарсил браузер. Браузер парсит HTML сверху вниз. Если ваш скрипт находится вверху страницы, то он не найдёт элементы ниже в странице — браузер их ещё не увидел и ничего о них не знает. Поэтому скрипты либо подключают в конце страницы, либо подписываются на событие DOM
          Content​
          Loaded
          , которое сигнализирует о том, что браузер распарсил весь HTML.

          </section

          Оцените статью
          ГИС ЖКХ