insertBefore错误,并未插入所有元素

时间:2011-06-16 08:24:26

标签: javascript

如果您使用标记字符串,例如在><之间放置空格,则效果会有所不同。

<!DOCTYPE html>
<head><title>insertBefore error</title></head>
<body>
<div id='myElement'>above this div 3 elements should be inserted
but actually only 2 are, text2 is missing</div>
<script  type="text/javascript">
    referenceTag = document.getElementById('myElement');
    var newElement = document.createElement('div');
    newElement.innerHTML = '<div>text1</div><pre>text2</pre><p>text3</p>';
    for (i=0; i<newElement.childNodes.length; i++) {
        alert(newElement.childNodes[i].tagName);
        //if you comment-out following line there are 3 alerts but otherwise only two.
        referenceTag.parentNode.insertBefore(newElement.childNodes[i],referenceTag);
    }
</script>
</body>

3 个答案:

答案 0 :(得分:3)

当您致电insertBefore时,您移动该节点,使其成为referenceTag.parentNode的孩子。此时它不再是newElement的孩子,因此newElement.childNodes会缩小一个。

然后递增i,以便继续跳过元素。

  1. 移动节点0
  2. 节点1变为节点0
  3. 移动 new 节点1并将旧节点1(和当前节点0)放在后面。
  4. 你可能想要:

    while (newElement.firstChild) {
            alert(newElement.firstChild.tagName);
            referenceTag.parentNode.insertBefore(newElement.firstChild,referenceTag);
    }
    

      

    如果您使用标签字符串,例如在&gt;&lt;之间放置空格,则效果会有所不同。

    效果实际上是相同的,但更难看。插入空格意味着不要使用以下行的数据结构:

    [ elementNode, elementNode, elementNode ]
    

    你有:

    [ elementNode, textNode, elementNode, textNode, elementNode ]
    

    由于您跳过其他所有节点,而其他每个节点都是一个完全由空格组成的文本节点,因此无法看到效果。

答案 1 :(得分:1)

使用以下内容插入节点时

referenceTag.parentNode.insertBefore(newElement.childNodes[i],referenceTag);

newElement.childNodes.length的长度总是减少1.此外,当您在其他元素之前删除元素时,元素的索引会发生变化,因此您应该存储for循环的长度并始终使用索引0:

 referenceTag = document.getElementById('myElement');
    var newElement = document.createElement('div');
    newElement.innerHTML = '<div>text1</div><pre>text2</pre><p>text3</p>';
    var storeLength = newElement.childNodes.length
    for (i=0; i<storeLength; i++) {
        alert(newElement.childNodes[0].tagName);
        //if you comment-out following line there are 3 alerts but otherwise only two.
     referenceTag.parentNode.insertBefore(newElement.childNodes[0],referenceTag);
    }

示例:http://jsfiddle.net/djttp/5/

答案 2 :(得分:1)

问题是newElement.childNodes是节点的实时集合。因此,无论何时访问它的属性,都会重新评估集合,更新集合以反映DOM的当前状态。

示例:

第一次迭代

i = 0
newElement.childNodes[0] == '<div>'
newElement.childNodes[1] == '<pre>'
newElement.childNodes[2] == '<p>'
newElement.childNodes.length == 3

<div>元素已预先添加。

第二次迭代:

i = 1
newElement.childNodes[0] == '<pre>'
newElement.childNodes[1] == '<p>'
newElement.childNodes.length == 2

<p>元素已预先添加。

第三次迭代:

i = 2
newElement.childNodes[0] == '<pre>'
newElement.childNodes.length == 1

循环停止,因为未满足条件。

@Quentin provided a good solution for this problem.