循环时JavaScript.children HTML集合长度问题

时间:2015-07-10 03:33:34

标签: javascript loops xmlhttprequest children

我正在尝试使用以下代码遍历从JavaScript的.children属性生成的HTMLCollection:

var articles = data.children;
var newsGrid = document.getElementById('js-news__grid');

for (var i = 0; i < articles.length; i++) {
   articles[i].classList.add('loading');
   newsGrid.appendChild(articles[i]);
};

data变量是成功XHR的片段。当我运行循环时,它只附加第一个子节点并且循环结束,并且在循环之前运行console.log(articles);时,它显示2个HTML元素(就像它应该)但是只有1的长度。如果我删除循环并运行console.log(articles);它显示像以前一样的2个HTML元素,但现在它的长度为2.

为了简单起见,我省略了我的XHR代码,因为从data.children生成的HTMLCollection看起来是正确的。以下是日志消息:

[article.news__item, article.news__item]
0: article.news__item
1: article.news__item
length: 2
__proto__: HTMLCollection

[article.news__item, article.news__item]
0: article.news__item
length: 1
__proto__: HTMLCollection

1 个答案:

答案 0 :(得分:2)

问题是.children是一个实时集合,当您将每个孩子移出容器时,它会更新。

在您的情况下,data有2个子项,因此在启动循环时articles.length为2,但在第一次迭代后您重新定位了第一个子项,这意味着articles object现在只包含1个元素,i现在是2,循环条件i < articles.length失败。

因此,一个简单的解决方案是使用反向循环

var articles = data.children;
var newsGrid = document.getElementById('js-news__grid');

for (var i = articles.length - 1; i >= 0; i--) {
    articles[i].classList.add('loading');
    newsGrid.appendChild(articles[i]);
};

另一个解决方案是将articles转换为普通数组

var articles = [].slice.call(data.children);

RobG建议的另一种方法是

var articles = data.children;
var newsGrid = document.getElementById('js-news__grid');

while (articles.length) {
    articles[0].classList.add('loading');
    newsGrid.appendChild(articles[0]);
};