как выполнить итерацию по HTMLCollection?

У меня есть некоторые элементы в моем HTML с классом node-item, я получаю к ним доступ в моем компоненте, используя:

let nodeItems = document.getElementsByClassName('node-item');

и когда я регистрирую nodeItems, он дает мне HTMLCollection[] с длиной 4.

Я пробовал много способов, но все еще не могу повторить nodeItems:

1- первая попытка:

let bar = [].slice.call(nodeItems);
for (var g of bar){
    console.log(g); //gives me nothing
} 

2-секундная попытка:

for(let c of <any>nodeItems) {
    console.log(c); //gives me nothing
}

И я пробовал итерацию массива и итерацию объекта, но все равно undefined или error. также пробовал:

let nodeItems = document.querySelector(selectors);

Но те же проблемы.


person Fateme Fazli    schedule 21.04.2018    source источник
comment
Оба подхода должны работать (хотя Array.from() будет чище, чем [].slice.call()). Вы уверены, что коллекция содержит элементы? Помните, что это список активных узлов. Пожалуйста, сделайте console.log(nodeItems.length).   -  person Bergi    schedule 21.04.2018
comment
Ваш код работает, когда вы делаете это в консоли, у вас есть еще пример?   -  person romuleald    schedule 21.04.2018
comment
@Bergi @romuleald Я регистрирую nodeItems, и он дает мне полную HTMLCollection, но когда регистрирую длину, он дает мне 0.   -  person Fateme Fazli    schedule 21.04.2018
comment
Тогда ваша настоящая проблема заключается в том, что коллекция пуста, когда вы пытаетесь ее перебрать, и она заполняется только позже (когда элементы DOM загружены).   -  person Bergi    schedule 21.04.2018
comment
@Bergi Это не дубликат перечисленных вопросов, потому что вопрос относится к TS. Я совершенно уверен, что где-то есть канонический вопрос TS.   -  person Estus Flask    schedule 21.04.2018
comment
@estus При чем здесь машинопись? Независимо от того, компилируется ли for of в итераторы или в подсчет индекса массива, он должен работать. Если регистрация длины дает 0, согласно комментарию OPs, то проблема заключается в использовании DOM в неподходящее время. Не могли бы вы снова закрыть его?   -  person Bergi    schedule 21.04.2018
comment
@Bergi Да, здесь актуальна длина 0. Он будет работать с for..of, потому что он компилируется в for, но будет ошибка компиляции (‹any› nodeItems - уродливый обходной путь для этого). Вы можете перечислить отмеченных вами обманщиков? Я не ожидал, что его сразу откроют.   -  person Estus Flask    schedule 21.04.2018
comment
@estus У меня был заголовок stackoverflow.com/questions/14028959/, а также канонический вопрос о console.log путанице с видоизмененными массивами   -  person Bergi    schedule 21.04.2018


Ответы (3)


nodeItems - это HTMLCollection, объект, подобный массиву.

Это итерация в современных браузерах. Итераторы поддерживаются при включенном downlevelIteration параметре компилятора, в этом случае он будет :

const nodeItems = document.getElementsByClassName('node-item');

for (const c of nodeItems) {
  // ...
}

Итерируемые объекты можно полифилить в старых версиях браузеров. core-js предоставляет полифилы для итераций DOM.

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

const nodeItems = Array.from(document.getElementsByClassName('node-item'));

for (const c of nodeItems) {
  // ...
}
person Estus Flask    schedule 21.04.2018
comment
У меня такой же случай, но это мне не помогает. - person chandrakant; 29.05.2018
comment
Нет причин отрицать правильный ответ. Если это не помогает, значит, в вашем случае что-то может отличаться. Вы можете задать свой вопрос и предоставить stackoverflow.com/help/mcve, чтобы пользователи могли воспроизвести проблему. - person Estus Flask; 29.05.2018
comment
Если я сделаю Array.from(), а затем typeof nodeItems, это все равно объект. - person geoidesic; 06.03.2019
comment
@geoidesic typeof ничего вам не скажет. Массивы - это объекты. - person Estus Flask; 06.03.2019

Просто используйте Array.from(document.getElementsByClassName('node-item')) или оператор распространения [...document.getElementsByClassName('node-item')] и используйте все, что вы бы использовали в массиве.

Кроме того, вы также можете использовать обычный цикл for

let nodeItems = document.getElementsByClassName('node-item');
for (let i = 0; i < nodeItems.length; i++) {
    // access current element with nodeItems[i]
}
person baao    schedule 21.04.2018
comment
Я пробую код, но консоль ничего не регистрирует. моя коллекция HTMLCollection заполнена, и я регистрирую ее, и при попытке [...document.getElementsByClassName('node-item')] это дает мне ошибку HTMLCollectionOf<Element>' is not an array type. - person Fateme Fazli; 21.04.2018

Вы можете использовать оператор распространения на document.querySelectorAll, чтобы получить массив.

Вот отрывок:

let nodeItems = [...(document.querySelectorAll('.class1'))];

for (var g of nodeItems) {
  console.log( g.innerHTML ); 
}
<div class='class1'>Text 1</div>
<div class='class1'>Text 2</div>
<div class='class1'>Text 3</div>

Документ: Spread

person Eddie    schedule 21.04.2018