0

我的代码应该在所有具有预定义类名的 div 中插入 HTML 内容,而不使用 jQuery,并且至少与 IE8 兼容(因此没有 getElementsbyClass)。

的HTML:

<div class="target">1</div>
<div class="target">2</div>
<div class="target">3</div>
<div class="target">4</div>

的JavaScript:

var elems = document.getElementsByTagName('*'), i;
    for (wwi in elems) {
        if((' ' + elems[wwi].className + ' ').indexOf(' ' + "target" + ' ') > -1) {
            elems[wwi].innerHTML = "YES";
            //elems[wwi].innerHTML = "<div>YES!</div>";
        }
    }

你可以在这里试试。

正如您在每个 div 中看到的那样,打印了 YES 一词。好吧,如果您评论elems[wwi].innerHTML = "YES";并替换 elems[wwi].innerHTML = "<div>YES!</div>"代码失败。我想是因为插入 div 元素会修改 DOM,因此 FOR 循环失败。我对吗?

好吧,我可以通过每次创建 innerHTML 时调用 for 循环来解决这个非常丑陋的问题,并且当我插入代码时,我可以添加一个类(如 data-codeAlreadyInserted = 1)以在下一次 FOR 传入该 div 时忽略它。但同样,这几乎是一个非常糟糕的解决方案,因为对于具有许多标签的普通网站,我什至可以冻结用户浏览器。

你怎么看?假设我不知道我在每个 innerHTML 调用中插入的标签数量。

4

3 回答 3

1

“我想是因为插入 div 元素会修改 DOM,从而导致 FOR 循环失败。我说的对吗?”

差不多。您的elems列表是在 DOM 更改时更新的实时列表。因为您在每次迭代中都添加了一个新的 div,所以列表会不断增长,因此您永远不会到达终点。

为避免这种情况,您可以进行反向迭代,

for (var i = elems.length-1; i > -1; i--) {
    // your code
}

或将列表转换为数组。

var arr = [];

for (var i = 0, len = list.length; i < len; i++) {
    arr.push(elems[i]);
}

for (i = 0; i < len; i++) {
    // your code
}
于 2013-06-26T12:48:50.850 回答
0

您可以获取活动节点列表的副本:

var nodes = [];
for (var i = 0, n = elems.length; i < n; ++i) {
    nodes.push(elems[i]);
}

然后使用适当的for循环,而不是for ... in遍历数组:

for (var i = 0, n = nodes.length; i < n; ++i) {
    ...
}

for ... in应该用于对象,而不是数组。

于 2013-06-26T12:48:42.667 回答
0

另一种方法是使用replaceChild 而不是innerHTML。它工作得更好,而且速度更快:

var newEl = elem[wwi].cloneNode(false);
newEl.innerHTML = html;
elem[wwi].parentNode.replaceChild(newEl, elem[wwi]);
于 2013-06-26T12:51:50.687 回答