Нативні еквіваленти jQuery методів – Частина 1: Вибірка DOM елементів
Така корисна бібліотека як jQuery, іноді здається зайвою, завантажити велику бібліотеку для того, щоб стягнути прості речі, як додавання обробника події або перемикання класу. З багатьма нативними методами, які тепер доступні і будучи набагато швидше, найкращий час, щоб відійти від jQuery на деякий час і вивчити деякі рідні еквіваленти.
У наступній серії постів я покажу вам корисні фрагменти коду, які дозволяють робити маніпуляції, для яких ви зазвичай використовуєте jQuery без необхідності, додавши ще 80 Кб + на свою сторінку. Кожен запис покаже jQuery метод із відповідним нативним методом. Пости не будуть розкривати всі моменти як навчальні посібники, але слід розглядати їх як коротке довідкове керівництво.
Частина 2: Робота з атрибутами та властивостями
Частина 4: Створення, вставка, переміщення та видалення елементів
Цей пост буде присвячений безлічі методів вибору DOM елементів.
Отримати елемент за його ID
jQuery
$('#myElement')
Нативний JS
document.getElementById('myElement') // IE 5.5+
// or
document.querySelector('#myElement') // IE 8+
Зауважте, що jQuery метод повертає об’єкт, в той час як нативні версії повертають вузол DOM дерева.
Отримати елементи за назвою тега (tagName)
jQuery
$('div')
Нативний JS
document.getElementsByTagName('div')
// or
document.querySelectorAll('div')
Отримати елементи за назвою класу (className)
jQuery
$('.some-class')
Нативний JS
document.getElementsByClassName('some-class')
// or
document.querySelectorAll('.some-class')
Зверніть увагу, що, як і jQuery $()
метод, querySelector
і querySelectorAll
обидва приймають рядковий CSS3 селектор.
Інший важливий момент це те, що всі методи в прикладах вище починають свій пошук з вершини DOM дерева, які не можуть бути ефективні при роботі з тонною DOM вузлів. Однак, ми можемо викликати методи безпосередньо на вузлі DOM дерева.
Приклад:
var parent = document.getElementById('myElement');
parent.getElementsByClassName('child-class');
Це дозволить почати пошук безпосередньо з parent
вузла та повернути всі дочірні елементи з ім’ям класу ‘child-class’
Отже, який із них використовувати?
Добре, у нас є getElementsByTagName
, getElementsByClassName
і querySelectorAll
, так який із них використовувати?
Хоч метод querySelectorAll
і є більш сучасним підходом і ближче до jQuery методу $(selector)
, так як він дозволяє використовувати в широкому діапазоні CSS3 селектори, є одна головна відмінність, яка може повернутися і вкусити вас у зад, якщо ви не знаєте цього.
Метод querySelectorAll
як і jQuery $(selector)
метод, буде повертати статичний NodeList
, тоді як getElementsByTagName
і getElementsByClassName
будуть повертати живий NodeList
.
Добре, то в чому відмінність?
Подумайте про статичний NodeList
як знімок DOM дерева, коли метод querySelectorAll
був викликаний. Все, що ви робите з DOM після виклику методу querySelectorAll
не буде відображено в NodeList
при поверненні. В той час, як живий NodeList
що повернув getElementsByTagName
і буде getElementsByClassName
.
Чому це так важливо?
Візьмемо наступний перелік елементів:
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
Давайте отримаємо елементи за допомогою методу querySelectorAll
var myItems = document.querySelectorAll('li');
Тепер порахуємо ці елементи:
console.log(myItems.length) // returns 4;
Додамо новий елемент до списку:
// Create a new <li> element
var newItem = document.createElement('li');
// And append it to the list
myItems[0].parentNode.appendChild(newItem);
Тепер давайте знову рахувати елементи:
console.log(myItems.length) // returns 4 again;
Ой, що сталося? Тепер у нас є 5 елементів у списку, але другий лічильник все ще показує 4 елементи!
У цьому полягає суть статичного NodeList
, істотна відмінність, яку вам потрібно знати при використанні querySelectorAll
перед getElementsByTagName
и getElementsByClassName
. Оскільки обидва останні методи повертають живий NodeList
, перерахунок при другій спробі мало повернути 5. Насправді, не важливо, яку кількість елементів ви додали або видалили, останні методи завжди відображатимуть зміни.
Звичайно, це відноситься тільки якщо DOM дерево змінюється після того, як викликається метод, якщо ви впевнені, що жодних змін у майбутньому не відбудеться, ви в безпеці що б використовувати метод querySelectorAll
.
Робочий приклад наведений вище можна знайти за цим посиланням: codepen.io/Mobius1/pen/jMjjZd.
Додатково прочитати: getElementById, getElementsByTagName, getElementsByClassName, querySelector, querySelectorAll
Додаткові селектори
Отримати перший елемент
jQuery
$('div:first-child')
// or
$('div').first();
Нативний JS
document.getElementsByTagName('div')[0]
// or
document.querySelectorAll('div')[0]
// or
document.querySelector('div')
Пам’ятайте, що ви можете замінити document
з DOM вузлом, щоб зробити пошук ефективнішим.
Також зазначимо, що querySelector
повертає перший відповідний Element
вузла, у той час як querySelectorAll
поверне NodeList
.
Отримати дочірні вузли елементів
jQuery
$('div').children();
Нативний JS
document.getElementsByTagName('div').childNodes // IE <9
// or
document.getElementsByTagName('div').children // IE 9+
Не використовуйте метод
childNodes
Не використовуйте якщо не знаєте що робите, або ви повинні підтримувати IE <9, так як він може повернути вузли елемента, що не є, як текстові вузли.
Отримати перший дочірній елемент
jQuery
$('#myList > li:first-child');
// or
$('#myList').children('li:first-child');
// or
$('#myList > li').first();
// or
$('#myList').children().first();
// and so on
Нативний JS
var myList = document.getElementById('myList');
myList.children[0] // IE 9+
// or
myList.firstChild // IE <9
// or
myList.firstElementChild // IE 9+
Метод
firstChild
має аналогічні підводні камені якchildNodes
.
Пам’ятайте, що метод jQuery як $()
, querySelector
і querySelectorAll
обидва підтримують складні селектори CSS3, тому також можуть бути використані нижче:
document.querySelector('ul').querySelector('li');
// or
document.querySelector('ul > li:first-child');
// or
document.querySelector('ul > li')
// and so on
У випадку з jQuery, є безліч способів отримання бажаного вузла у наведеному вище прикладі, таким чином просто виберіть той, який відповідає вашим потребам, але слід зазначити що (залежно від браузера) старі getElementsByTagName
і getElementsByClassName
методи можуть бути набагато швидше, ніж нові рідні та jQuery методи: запустити тест
Отримати останній дочірній елемент
jQuery
$('#myList > li:last-child');
// or
$('#myList').children('li:last-child');
// or
$('#myList > li').last();
// or
$('#myList').children().last();
// and so on
Нативний JS
var myList = document.getElementById('myList');
myList.lastChild // IE <9
// or
myList.children[myList.length - 1] // IE 9+
// or simply
myList.lastElementChild // IE 9+
Як і c
firstChild
іchildNodes
,lastChild
слід використовувати тільки якщо ви збираєтеся підтримувати IE <9.
Додатково прочитати: firstChild, lastChild, childNodes, nodeType, children, firstElementChild, lastElementChild
Отримати батька елемента
jQuery
myElement.parent();
Нативний JS
myElement.parentNode
Отримати наступний елемент
jQuery
myElement.next();
Нативний JS
myElement.nextSibling // IE <9
// or
myElement.nextElementSibling // IE 9+
Нативні методи будуть повертати null
, якщо MyElement
є останнім нащадком його батька.
Отримати попередній елемент
jQuery
myElement.prev();
Нативний JS
myElement.previousSibling // IE <9
// or
myElement.previousElementSibling // IE 9+
Нативні методи будуть повертати null
, якщо MyElement
є першим нащадком його батька.
nextSibling
іpreviousSibling
методи повинні розглядатися так само, як іchildNodes
,firstChild
іlastChild
, для їхнього повернення вузлів за винятком HTMLElements.
Якщо вам потрібно використовувати будь-який з цих методів для підтримки старих браузерів, ви можете перевірити nodeType
для безпеки. HTMLElement nodeType дорівнює 1, якщо інше значення відмінне від 1, то у вас не HTMLElement.
Немає нативної альтернативи?
Обхід DOM дерева може бути непростим завданням (особливо для новачків) і на щастя jQuery має багато корисних методів, щоб допомогти. Однак не всі методи jQuery мають рідний еквівалент.
Отримати найближчий елемент вгору по DOM дереву (предка) відповідний селектору
jQuery
// Get the first ancestor with the className 'some-class'
var closestElem = $('#myElement').closest('.some-class');
Нативный JS
Незважаючи на наявність рідної версії jQuery методу closest()
, вона експериментальна, і тому має використовуватися на продакшені.
Додатково прочитати: Element.closest()
Давайте створимо наш власний натомість.
function closest(el, selector) {
var first = selector.charAt(0);
// Traverse the DOM tree using parentNode
for ( ; el && el !== document && el.nodeType === 1; el = el.parentNode ) {
// Selector is a class
if ( first === '.' && el.classList.contains( selector.substr(1) ) ) {
return el;
}
// Selector is a tagName
if ( el.tagName.toLowerCase() === selector ) {
return el;
}
}
return null;
};
var closestElem = closest(document.getElementById('#myElem'), '.some-class'));
Функція вище не включає перевірки більш складних атрибутів, таких як data-*
для скорочення, а також не включає на перевірку ID, як правило, можна було викликати getElementById
щоб знайти його.
Ось і все сьогодні. У наступній посаді ми розглядатимемо нативні методи jQuery attr()
, prop()
, addClass()
, hasClass()
, removeClass()
та методи “поліфілів” для старих браузерів.
Частина 2: Робота з атрибутами та властивостями
Частина 4: Створення, вставка, переміщення та видалення елементів