Що повертають методи querySelectorAll та getElementsBy *?


151

Чи getElementsByClassName(і подібні функції, як getElementsByTagNameі querySelectorAll) працюють так само, getElementByIdчи вони повертають масив елементів?

Причина, яку я прошу, полягає в тому, що я намагаюся змінити стиль усіх елементів, що використовують getElementsByClassName. Дивись нижче.

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

37
Підказка, як правило, в назві: getElementsByClassName()передбачає множину, тоді як getElementById()передбачає елемент однини елемента.
Девід каже повернути Моніку

1
Я розумію, що мені просто не було сенсу, що ви не можете змінити всі елементи з цим іменем класу, використовуючи наведений вище код, замість того, щоб прокручувати масив. jquery шлях набагато кращий, мені просто цікаво було про js шлях
1212

1
Може бути корисним також: stackoverflow.com/questions/3871547/…
kapa

Відповіді:


152

Ваш getElementById()код працює, оскільки ідентифікатори повинні бути унікальними, тому функція завжди повертає рівно один елемент (або nullякщо жодного не було знайдено).

Однак getElementsByClassName(), querySelectorAll()і інші getElementsBy*методи повертають масив, як набір елементів. Повторіть його, як і з реальним масивом:

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

Якщо ви віддаєте перевагу щось коротше, подумайте про використання jQuery :

$('.myElement').css('size', '100px');

1
Чи стосується <iframe>це також те, що також є частиною вашого домену
JMASTER B

3
Настав 2018 рік ... Просто створіть функцію обгортки, querySelectorAll()і ви можете мати хороший короткий код без великої залежності від старої школи. qSA(".myElement").forEach(el => el.style.size = "100px")Можливо, замовник отримає зворотний дзвінок. qSA(".myElement", el => el.style.size = "100px")

2
"Якщо ви віддаєте перевагу щось коротше, подумайте про додавання величезної бібліотеки до свого проекту" Я знаю, що 2012 рік був іншим часом, але навіть тоді я вважав би цей біт смішним.
CoryCoolguy

1
" Ітерація над нею, як і з реальним масивом ... Обережно, getElementsByClassName повертає живий NodeList, який може бути несподівано змінений під час циклу, наприклад, якщо ім'я класу, для якого вони були обрані, видалено. ;-)
RobG

20

Ви використовуєте масив як об'єкт, різниця між getElementbyIdі getElementsByClassNameполягає в тому, що:

  • getElementbyIdповерне об'єкт Element або null, якщо не знайдено жодного елемента з ідентифікатором
  • getElementsByClassNameповерне живий HTMLCollection , можливо, довжиною 0, якщо не знайдено відповідних елементів

getElementsByClassName

getElementsByClassName(classNames)Метод приймає рядок , яка містить невпорядкований набір унікальних розділених пробілами лексем , що представляють класи. При виклику метод повинен повернути живий NodeListоб'єкт, що містить усі елементи в документі, у яких є всі класи, зазначені в цьому аргументі, отримавши класи, розділивши рядок на пробіли. Якщо в аргументі немає лексем, то метод повинен повернути порожній NodeList.

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

getElementById

Метод getElementById () отримує доступ до першого елемента із вказаним ідентифікатором.

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

у вашому коді рядки:

1- document.getElementsByClassName ('myElement'). Style.size = '100px';

НЕ буде працювати, як очікувалося, оскільки getElementByClassNameмасив поверне масив, а масив НЕ матиме styleвластивість, ви можете отримати доступ до кожного element, повторивши їх.

Ось чому функція getElementByIdпрацювала для вас, ця функція поверне прямий об’єкт. Тому ви зможете отримати доступ до styleвласності.


Зауважте, що параметри whatwg , що реалізуються браузерами, відрізняються від w3c, які тут, колишні (а отже, і поточні браузери) повертають HTMLCollection для getElementsByClassName, а не NodeList. Незначні, але можуть заплутати деякі.
Каїдо

@ Kaiido - практична різниця в тому, що ...? Наскільки я розумію, NodeList - це загальна колекція елементів DOM і доступна в будь-якій DOM, не тільки в HTML DOM (наприклад, XML DOM), тоді як HTMLCollection призначена для HTML DOM (очевидно). Єдина відмінність , яке я можу бачити це namedItem метод з HTMLCollection .
RobG

PS Nit pick: посилання для WHATWG HTML Living Standard та стандарту W3C HTML 5.2 . Зіпсований вибором. ;-) Не має жодної різниці в точці, яку ви підняли.
RobG

@RobG NodeList має багато методів , недоступних у HTMLCollection.
Каїдо

@ Kaiido - звичайно, але forEach не вказаний як частина інтерфейсу для колекції або NodeList від W3C або WHATWG, він задається окремо, наприклад, як властивість загальних колекцій у специфікації Web IDL, тому має застосовуватися як до колекцій, так і до NodeLists (хоча я погоджуюся з вашою думкою, що колекція, повернена getElementsByClassName , не має методу forEach ). Я думаю, що підсумок полягає в тому, що достатньо історії для гарної відповіді. :-)
RobG

11

На цій сторінці взято наступне опис :

Метод getElementsByClassName () повертає колекцію всіх елементів у документі із вказаним іменем класу як об’єкт NodeList.

Об'єкт NodeList являє собою сукупність вузлів. До вузлів можна отримати доступ за номерами індексу. Індекс починається з 0.

Порада: Ви можете скористатися властивістю довжини об'єкта NodeList для визначення кількості елементів із вказаним іменем класу, після чого ви зможете переглядати всі елементи та витягувати потрібну інформацію.

Отже, як параметр getElementsByClassNameбуде прийнято ім'я класу.

Якщо це ваше тіло HTML:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

то var menuItems = document.getElementsByClassName('menuItem')повертає колекцію (а не масив) трьох верхніх <div>s, оскільки вони відповідають заданому імені класу.

Потім ви можете повторити <div>колекцію цих вузлів ( у цьому випадку) за допомогою:

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

Детальніше про відмінності між елементами та вузлами див. У цій публікації .


11

ES6 забезпечує Array.from()метод, який створює новий екземпляр масиву з об’єкта, подібного до масиву або ітерабельного.

let boxes = document.getElementsByClassName('box');

Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

Як ви бачите всередині фрагмента коду, після використання Array.from()функції ви зможете маніпулювати над кожним елементом.


Те саме рішення з використанням jQuery.

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>


7

Іншими словами

  • document.querySelector()вибирає лише перший один елемент зазначеного селектора. Таким чином, він не випльовує масив, це єдине значення. Подібно до того, document.getElementById()що отримує лише ID-елементи, оскільки ідентифікатори повинні бути унікальними.

  • document.querySelectorAll()вибирає всі елементи із зазначеним селектором та повертає їх у масив. Подібно лише document.getElementsByClassName()до класів і document.getElementsByTagName()тегів.


Навіщо використовувати querySelector?

Він використовується лише з метою простоти і стислості.


Навіщо використовувати getElement / sBy? *

Швидше виконання.


Чому така різниця в продуктивності?

Обидва способи вибору мають на меті створити NodeList для подальшого використання. querySelectors генерує статичний NodeList з селекторами, таким чином його слід спочатку створити з нуля.
getElement / sBy * негайно адаптує існуючий живий NodeList поточного DOM.

Отже, коли використовувати метод, який залежить від вас / вашого проекту / вашого пристрою.


Інформація

Демонстрація всіх методів
Тест продуктивності документації NodeList


4

Він повертає список, схожий на масив.

Ви зробите цей масив як приклад

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

4

Ви можете отримати один елемент, запустивши

document.querySelector('.myElement').style.size = '100px';

але це буде працювати для першого елемента з класом .myElement.

Якщо ви хочете застосувати це для всіх елементів класу, я пропоную вам використовувати

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

4
/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name


0

Відповідь на конкретний випадок Дрензі ...

Ви можете створити функцію, яка працюватиме для будь-якого з wordелементів і передаватиме номер того, який ви хочете перетворити, наприклад:

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.