索引HtmlCollection或NodeList

时间:2019-07-17 23:14:25

标签: javascript arrays dom htmlcollection

我试图克隆一个节点,该节点是另一个节点的子节点,但是js不允许我为HTMLCollection / NodeList数据类型建立索引。每当我尝试索引该数据类型时,它总是导致未定义的值。即使按照Most efficient way to convert an HTMLCollection to an Array将该数据类型转换为数组,我仍然无法索引该数组。

var viewports = document.getElementsByClassName('imageViewerViewport');
console.log(viewports[0].childNodes)  // In the console shows the children I expect to see
console.log(viewports[0].childNodes.item(0))  // Nothing shows up  - undefined
console.log(viewports[0].childNodes.item(1))  // Nothing shows up  - undefined
console.log(viewports[0].children.item(0))  // Nothing shows up  - undefined
console.log(viewports[0].children.item(1))  // Nothing shows up  - undefined    
console.log(viewports[0].childNodes[0])  // Nothing shows up  - undefined
console.log(viewports[0].childNodes[1])  // Nothing shows up  - undefined    
console.log(viewports[0].children[0])  // Nothing shows up  - undefined
console.log(viewports[0].children[1])  // Nothing shows up  - undefined
console.log("Here")
var second_canvas = viewports[0].children.item(1).cloneNode(true);  // Error that is detailed below
viewports[1].appendChild(second_canvas);

克隆节点会产生错误:Cannot read property 'cloneNode' of undefined

1 个答案:

答案 0 :(得分:0)

所以答案是并非所有childNodes都是有效的Node 这是详细版本,我们在其中记录以显示无效节点。

const cloneThings = () => {
  document.querySelectorAll('.cloneMyChildren').forEach(parentNode => {
    console.log(parentNode.classList.length);
    parentNode.childNodes.forEach(child => {
      console.log(child.outerHTML); // This is here to show, the child nodes are NOT all HTMLElements.
      if(child.outHTML) {
        const childClone = child.cloneNode(true);
        childClone.classList.add('clone');
        document.body.appendChild(childClone);
      }
    });
  });
};

document.addEventListener('click', ({ target }) => {
  if(target.matches('button')) {
    cloneThings();
  }
});
.cloneMe {
  border: 1px solid red;
}

.clone {
  border: 1px solid blue;
}
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<button>Clone Stuff</button>

这是一个更简洁的版本。

const cloneThings = () => {
  Array.from(document.querySelectorAll('.cloneMyChildren'))
       .flatMap(p => Array.from(p.childNodes).filter(c => c.outerHTML !== undefined))
       .forEach(n => {
          const childClone = n.cloneNode(true);
          childClone.classList.add('clone');
          document.body.appendChild(childClone);       
       });
};

document.addEventListener('click', ({ target }) => {
  if(target.matches('button')) {
    cloneThings();
  }
});
.cloneMe {
  border: 1px solid red;
}

.clone {
  border: 1px solid blue;
}
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<div class="cloneMyChildren">
  <span class="cloneMe">Clone Me</span>
  <span class="cloneMe">Clone Me</span>  
</div>
<button>Clone Stuff</button>