简体   繁体   English

从 DOM (JS) 中删除多个子项

[英]Remove multiple children from DOM (JS)

I am trying to remove certain children from DOM by iterating through them.我试图通过迭代它们来从 DOM 中删除某些子项。 I have a table, and I am looping through the children and removing some like this:我有一张桌子,我正在遍历孩子们并删除一些这样的:

for (const row of table.children) {
  const testRow = row.children[2];
  if (testRow.textContent === "false") {
    table.removeChild(row);
  }
}

When this code is run, some of the children that meet the condition testRow.textContent === "false" are removed, but other rows that meet the condition are not removed .运行这段代码时,部分满足条件testRow.textContent === "false"的子项被移除,但其他满足条件的行没有被移除

Logging out t.children.lengh as the loop goes on reveals that the size is decreasing (due to the children being removed).随着循环的进行注销t.children.lengh表明大小正在减小(由于子级被删除)。 My theory is that removing a child messes up the iterator.我的理论是删除一个孩子会弄乱迭代器。 I tried rewriting this code as a for loop and got the same result: some children are "skipped over" and not removed.我尝试将此代码重写为 for 循环并得到相同的结果:一些孩子被“跳过”而不是被删除。

Ideas on how to remove certain children of a DOM element (based on dynamically pulled data)?关于如何删除 DOM 元素的某些子元素的想法(基于动态拉取的数据)?

This uses deleteRow taking the index of the row and using a traditional for loop iterating backwards from the end of the table rows to the beginning, it also utilizes the rows property of the table element:这使用deleteRow获取行的索引并使用传统for循环从表行的末尾向后迭代到开头,它还利用了表元素的rows属性:

 window.addEventListener('DOMContentLoaded', function(){ const tbl = document.querySelector('table'); for(let a = tbl.rows.length - 1; a >= 0; a--){ //you can modify this next condition to match what you want if(tbl.rows[a].cells[0].textContent === "Even"){ tbl.deleteRow(a); } } });
 <table> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> <tr><td>Even</td></tr> <tr><td>Odd</td></tr> </table>

table.children is anHTMLCollection ; table.children是一个HTMLCollection it gets updated as you change the document.它会随着您更改文档而更新。 You can convert it to a normal array so that changes to the DOM won't affect the contents that you're iterating through.您可以将其转换为普通数组,以便对 DOM 的更改不会影响您正在迭代的内容。

In the example below I've used the spread operator ( ... ) to create the new array, but you could use Array.from instead eg Array.from(tbody.children) .在下面的示例中,我使用扩展运算符 ( ... ) 创建新数组,但您可以使用 Array.from 代替,例如Array.from(tbody.children)

 const tbody = document.querySelector('table tbody'); console.log(tbody.children.constructor.name); for (const row of [...tbody.children]) { const testRow = row.children[1]; if (testRow.textContent === "false") { tbody.removeChild(row); } }
 <table> <tbody> <tr><td>A</td><td>true</td></tr> <tr><td>B</td><td>false</td></tr> <tr><td>C</td><td>false</td></tr> <tr><td>D</td><td>true</td></tr> <tr><td>E</td><td>false</td></tr> <tr><td>F</td><td>true</td></tr> </tbody> </table>

Because [...tbody.children] is a normal array you can use functions like filter and forEach if you like, eg:因为[...tbody.children]是一个普通数组,您可以根据需要使用 filter 和 forEach 等函数,例如:

 const tbody = document.querySelector('table tbody'); [...tbody.children] .filter((row) => row.cells[1].textContent === "false") .forEach((row) => { tbody.removeChild(row); });
 <table> <tbody> <tr><td>A</td><td>true</td></tr> <tr><td>B</td><td>false</td></tr> <tr><td>C</td><td>false</td></tr> <tr><td>D</td><td>true</td></tr> <tr><td>E</td><td>false</td></tr> <tr><td>F</td><td>true</td></tr> </tbody> </table>

This solution I found works for all DOM types (vs just tables in Ryan Wilson's answer ).我发现这个解决方案适用于所有 DOM 类型(与Ryan Wilson 的答案中的表格相比)。 Just decrement the index each time a DOM object is removed so that it will re-run the loop for the new i th element (because the previous will have been removed):每次删除 DOM 对象时只需减少索引,以便它将为新的第i个元素重新运行循环(因为前一个元素将被删除):

for (let i = 0; i < t.children.length; i++) {
  const row = table.children[i];
  const testRow = row.children[2];
  if (testRow.textContent === "false") {
    table.removeChild(row);
    i--;
  }
}

If the elements are empty, you could use the css :empty selector:如果元素为空,则可以使用 css :empty选择器:

 setTimeout(()=>{ for (let el of document.querySelectorAll('tr td:empty')){ el.remove() } },2000)
 td {border: 1px solid black;height:30px;}
 <table> <tr><td>text</td></tr> <tr><td></td></tr> <tr><td>text</td></tr> <tr><td></td></tr> </table>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM