6 Июля 2018 JavaScript Перевод

15 методов HTML элементов о которых вы, возможно, никогда не слышали

img

Для начинающих

Давайте обсудим разницу между HTML и DOM.

Очевидно, что простой старый элемент <table> - это HTML. Вы можете использовать его в файле с .html в конце. У него есть набор атрибутов, которые влияют на то, как он выглядит и ведет себя.

На это всё. Он не имеет никакого отношения к JavaScript.

DOM - это то, что связывает ваш JavaScript код с элементами HTML в документе, поэтому вы можете взаимодействовать с такими элементами, как объекты.

Это объектная модель документа.

Каждый тип элемента в HTML имеет свой собственный DOM-интерфейс, который определяет свойства (которые обычно сопоставляются с атрибутами на HTML элементе) и методы. Например, <table> имеет интерфейс под названием HTMLTableElement.

Вы можете получить ссылку на определенный элемент, написав что-то вроде этого:

const searchBox = document.getElementById('search-box');

Затем у вас появится доступ ко всем свойствам и методам, доступных для выбранного элемента. Например, вы можете получить доступ к свойству value с помощью searchBox.value или поместить курсор в поле, вызвав searchBox.focus().

Спасибо, что посетили мой 58-й секундный курс по DOM.

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

К счастью для вас, просмотр спецификаций и написание статей - два из моих любимых способов не сойти с ума. Так что вот так...

Если вы хотите поиграть и имеете в своем распоряжении какой-нибудь браузер с DevTools, то можете выбрать элемент в дереве элементов, а затем ввести $0 в консоли. Это дает вам ссылку на элемент, который вы выбрали. Чтобы увидеть элемент как объект, введите dir($0).

В консоли есть много вещей, которые вы можете использовать.

#1 методы table

Скромная таблица (все еще один из способов для построения разметки веб-сайта) имеет немало отличных методов, которые являются такими же простыми, как сборка стола из IKEA.

Вот пример:

const tableEl = document.querySelector('table');

const headerRow = tableEl.createTHead().insertRow();
headerRow.insertCell().textContent = 'Make';
headerRow.insertCell().textContent = 'Model';
headerRow.insertCell().textContent = 'Color';

const newRow = tableEl.insertRow();
newRow.insertCell().textContent = 'Yes';
newRow.insertCell().textContent = 'No';
newRow.insertCell().textContent = 'Thank you';

Не видно ни одного document.createElement().

Метод .insertRow() даже вставляет <tbody> за вас, если вы вызываете его непосредственно в элементе таблицы. Разве это не здорово?

#2 scrollIntoView()

Было ли такое что, когда у вас есть #something в URL-адресе, и, при загрузке, браузер прокручивает страницу, чтобы вы могли видеть элемент с этим идентификатором?

Это действительно разумно, но это не сработает, если вы передаете этот элемент после загрузки страницы.

Вы можете вручную воссоздать это поведение с помощью:

document.querySelector(document.location.hash).scrollIntoView();

#3 hidden

Хорошо, это не метод, но если вы хотите поспорить, я скажу вам, что за кулисами, вероятно, есть сеттер, и это ведь метод, верно?

Во всяком случае, вы когда-либо делали myElement.style.display='none', чтобы скрыть элемент? Прекратите так делать!

Вы можете просто указать:

myElement.hidden = true.

#4 toggle()

Да, это тоже не метод элемета, это метод свойства элемента. В частности, это метод добавления/удаления класса из элемента с помощью myElement.classList.toggle('some-class').

И если вы когда-либо добавляли класс с выражением if, вас нужно посадить под замок.

Вы должны были просто передать второй параметр методу toggle(). Если это произойдет, ваш класс будет добавлен в элемент.

el.classList.toggle('some-orange-class', theme === 'orange');

Я знаю, вы думаете - это не то, что означает слово «toggle», а хорошие люди в Internet Explorer согласны с вами и протестуют, не реализуя логику второго параметра вообще.

Поэтому беру свои слова назад, вы не должны быть заперты. На свободу!

#5 querySelector()

Хорошо, вы это уже знаете, но я подозреваю, что ровно 17% из вас не знали, что можно использовать этот метод на любом элементе.

Например, myElement.querySelector('. My-class') будет соответствовать только элементам, которые имеют класс my-class и являются потомками myElement.

#6 closest

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

myElement.closest('article').querySelector('h1');

Берёт первый <article>, затем возвращает первый <h1>.

#7 getBoundingClientRect()

Метод возвращает аккуратный маленький объект с некоторыми подробными сведениями об элементе, которые вы ему задали.

{
 x: 604.875,
 y: 1312,
 width: 701.625,
 height: 31,
 top: 1312,
 right: 1306.5,
 bottom: 1343,
 left: 604.875
}

Будьте осторожны:

  • Этот метод вызывает перерисовку. В зависимости от устройства и сложности вашей страницы — это может занять несколько миллисекунд. Поэтому следите за тем, если вы вызываете его повторно, например, в анимации.
  • Некоторые браузеры возвращают не все эти значения. Потому что зачем они?

#8 matches()

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

Максимальная сложность:

if (myElement.className.indexOf('some-class') > -1) {
 // do something
}

Лучше, но ничего общего с этой статьёй:

if (myElement.className.includes('some-class')) {
 // do something
}

Лучший вариант:

if (myElement.matches('.some-class')) {
 // do something
}

#9 insertAdjacentElement()

Я узнал об этом на днях! Это похоже на appendChild(), но дает немного больше контроля над тем, куда вы добавляете этого ребенка.

parentEl.insertAdjacentElement('beforeend', newEl) это то же самое, что и parentEl.appendChild(newEl), но вы также можете указать beforebegin или afterbegin или afterend, чтобы поместить его в те места, которые предлагают эти имена.

Такой отличный контроль!

#10 contains()

Вы когда-нибудь хотели знать, находится ли один элемент внутри другого элемента? Я хочу знать об этом все время.

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

const handleClick = e => {
 if (!modalEl.contains(e.target)) modalEl.hidden = true;
};

Здесь modalEl является ссылкой на мой модальное окно, и e.target выберет любой элемент.

Забавный факт, в 100% случаев, когда я это делаю, то с первой попытки ошибаюсь в логике.

#11 getAttribute()

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

Помните, я упоминал выше, что свойства обычно относятся к атрибутам?

Одним из примеров, когда это не так, является атрибут href для элемента, такого как <a href="/animals/cat">Cat</a>.

el.href не вернет /animals/cat, как и следовало ожидать. Это связано с тем, что элемент реализует интерфейс HTMLHyperlinkElementUtils, который имеет кучу вспомогательных свойств, таких как protocol и hash, которые рассказывают вам о таргете ссылки.

Одним из этих полезных свойств является href, который даст вам полный URL-адрес со всеми обрезками, а не относительным URL-адресом в атрибуте.

Таким образом, вам нужно будет использовать el.getAttribute('href'), если вы хотите, чтобы точная строка находилась внутри атрибута href.

#12 Трио элемента dialog

Относительно новый элемент <dialog> имеет два хороших и один удивительный метод. show() и close() будут делать именно то, что вы ожидаете от них, и это нормально, я полагаю.

Но showModal() будет показывать <dialog> поверх всего остального, расположенного на странице, так же как и модальные окна. Нет необходимости в z-index или ручном добавлении затемненного фона или прослушивания ключа выхода, чтобы закрыть его. Браузер знает, как работают модальные окна, и сделает все это за вас.

И это потрясающе.

#13 forEach()

Иногда, когда вы получаете ссылку на список элементов, вы можете перебирать их через forEach().

for() – циклы из 2014.

Предположим, вы хотели вывести URL-адреса всех ссылок на странице. Вы можете сделать так, если хотите увидеть ошибку:

document.getElementsByTagName('a').forEach(el => {
   console.log(el.href);
});

Или вы можете сделать это:

document.querySelectorAll('a').forEach(el => {
   console.log(el.href);
});

Это происходит потому, что getElementsByTagName и другие методы get... возвращают HTMLCollection, а querySelectorAll возвращает NodeList.

Интерфейс NodeList дает нам метод forEach() (наряду с keys(), values() и entries()).

Было бы лучше, если бы они все возвращали массивы, а не пытались придумывать свои совсем не-массивы. Но не бойтесь, потому что добрые люди в ECMA дали нам Array.from(), который превратит все, что выглядит, как массив, в массив.

И это работает:

Array.from(document.getElementsByTagName('a')).forEach(el => {
   console.log(el.href);
});

И бонус: создав массив, вы можете использовать методы map() и filter() и reduce() или любые другие методы массива. Например, возвращая массив внешних ссылок без причины:

Array.from(document.querySelectorAll('a'))
 .map(el => el.origin)
 .filter(origin => origin !== document.origin)
 .filter(Boolean);
.filter(Boolean) - мой любимый способ заставить будущего меня почесывать голову, пытаясь понять, что оно делает.

#14 Forms

Скорее всего, уже знаете, что <form> имеет метод submit(). Несколько менее вероятно, что вы знаете, что формы имеют метод reset() и reportValidity(), если вы используете проверку на своих элементах формы.

Вы также можете использовать свойство elements формы с точечной нотацией для ссылки на элемент по его атрибуту name. Например, myFormEl.elements.email вернет элемент <input name="email" />, который принадлежит <form> («принадлежит» - не обязательно означает «является потомком»).

Я солгал вам. elements не возвращают список элементов вообще. Он возвращает список элементов управления (и, конечно же, это не массив, потому что зачем ему это делать?)

Пример: если у вас есть три переключателя, каждый с именем animal, то formEl.elements.animal даст вам ссылку на этот набор переключателей (1 элемент управления, 3 элемента).

И formEl.elements.animal.value вернет значение выбранного переключателя.

Это странный синтаксис, если вы думаете об этом. Разбивайте его, formEl - это элемент, elements - это HTMLFormControlsCollection, не-массив, где каждый элемент не обязательно является элементом HTML. animal имеет несколько переключателей, объединенных только потому, что они имеют один и тот же атрибут имени (для этого есть интерфейс RadioNodeList), а value просматривает атрибут value любого переключателя в коллекции.

#15 select()

Я, наверное, должен был организовать статью так, чтобы последний метод был самым интересным. В любом случае, метод .select() выделит весь текст в любом input, который вы вызываете.

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

Оригинал: 15 HTML element methods you’ve potentially never heard of