遍历具有相同类的元素并删除它们

时间:2019-04-17 06:09:25

标签: javascript html css

我正在构建一个应用程序,我需要从标题中删除具有特定类的所有链接元素。我已经建立了一个在w3schools编辑器中遇到的问题的示例。

出于重现问题的目的,我在标题中添加了多个相同的链接,并添加了“ link-to-remove”类:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">

这是我用来删除链接的功能:

function removeLinks() {
  const head = document.getElementsByTagName('head')[0];
        const links = head.getElementsByClassName('link-to-remove');
        for(let i = 0; i < links.length; i++) {
            head.removeChild(links[i]);
        }
}

该函数具有删除所有链接元素的逻辑,但每次仅删除少数几个。只有多次按下触发该功能的按钮后,所有链接才会被删除。 (在示例中,当引导表格样式消失时,所有链接都被删除)

示例: https://www.w3schools.com/code/tryit.asp?filename=G36L0TRX06V3

我需要在此功能中进行哪些更改,使其在首次触发时删除所有链接?

4 个答案:

答案 0 :(得分:7)

问题是getElementsByClassName返回一个 live HTMLCollection-如果在迭代过程中从其中删除一个元素,则该集合将在更改时更改。例如:

const foos = document.getElementsByClassName('foo');
console.log(foos[1].textContent);
foos[0].remove();
console.log(foos[1].textContent);
<div class="foo">a</div>
<div class="foo">b</div>
<div class="foo">c</div>

这很不直观。要么向后遍历整个集合(例如,从length - 1length - 2,... 0),以确保遍历每个元素,或者使用querySelectorAll,返回 static NodeList

const links = head.querySelectorAll('.link-to-remove');

querySelectorAll的另一个好处是,较新的浏览器在NodeLists上支持forEach,因此您可以直接对其进行迭代,而不必使用难看的for循环:

document.querySelectorAll('head .link-to-remove').forEach((removeMe) => {
  removeMe.remove();
});

(如您所见,如果将head放入传递给head的查询字符串中,则无需选择querySelectorAll-您也可以remove()元素,而不必引用其父元素并使用removeChild

答案 1 :(得分:3)

当您从DOM中删除元素时,getElementsByTagName方法将返回一个实时HTML元素集合,该元素将被更新,因此由于该元素的索引正在更改,它将跳过某些元素。

要使其使用保留集合长度并向后迭代的变量起作用。

function removeLinks() {
  const head = document.getElementsByTagName('head')[0];
        const links = head.getElementsByClassName('link-to-remove');
        let i = links.length;
        while(i--) {
            head.removeChild(links[i]);
        }
}

或者,您也可以使用forEach

function removeLinks() {
  const head = document.getElementsByTagName('head')[0];
  const links = head.getElementsByClassName('link-to-remove');
  links.forEach(el => el.remove())     
}

使用querySelectorAllforEachremove方法更简单。

function removeLinks() {
  document.querySelectorAll('head .link-to-remove').forEach(el => el.remove())     
}

答案 2 :(得分:1)

您必须将样式表设置为禁用,因为它会将css样式保留在内存中,因此删除该元素将不起作用,如果我没有记错的话,在某些情况下它也可能导致其崩溃。

function removeLinks() {
  const head = document.getElementsByTagName('head')[0];
        const links = head.getElementsByClassName('link-to-remove');
        for(let i = 0; i < links.length; i++) {
            links[i].disabled = true;
        }
}

例如:document.styleSheets[0].disabled = true;

jQuery方式=> $('link[title=mystyle]')[0].disabled=true;

答案 3 :(得分:0)

可以像其他任何标签一样删除

<link>s .getElementsByClassName() .getElementsByTagName() .getElementsByName() 等较旧的方法是 Live HTMLCollections < / strong>(类似数组的对象),因此.length会在每次迭代时更新,它会减少循环并过早地结束循环。您可以通过禁用每个<link>而不是删除它们(不要触摸.length)来实现目标,或使用返回静态 NodeList (数组为像对象)一样更通用的 .querySelectorAll() 方法。另一种方法是通过 Array.from() 此演示将类似数组的对象转换为数组:

  • 显示了两个不同的接口来处理<link>

    • 第一个使用 CSSStyleSheet 界面的styleSheet对象

      • 点击黄色按钮以禁用目标<link>s
    • 使用.querySelectorAll()

    • DOM的第二个 HTMLLinkElement 接口

      • 单击红色按钮以删除目标<link>s

      • 注意是一个实时HTML集合,因此在删除link.link-to-remove时可以在控制台中对其进行准确计数。

要正确测试每个示例,请重新运行演示,然后单击另一个按钮。

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" class="link-to-remove">
</head>

<body>
  <button class='btn btn-warning'>CLICK TO DISABLE ALL STYLESHEETS</button>
  <a href='#/' class='btn btn-danger'>REMOVE ALL <code>link.link-to-remove</code></a>

  <script>
    // Collect all stylesheets and convert to an array
    let sheets = Array.from(document.styleSheets);

    console.log('=========STYLESHEET QTY===========');

    // Test: Check how many stylesheets there are
    console.log('This page has ' + sheets.length + ' stylesheets');

    console.log('=============All HREF=============');

    // Test: View each stylesheet href
    for (let sheet of sheets) {
      console.log(sheet.href);
    }

    document.querySelector('button').onclick = function(e) {
      // Start disabling all stylesheets beginning at the 3rd position 
      for (let s = 0; s < sheets.length; s++) {
        if (s >= 2) {
          sheets[s].disabled = true;
        }
      }

      console.log('=============DISABLED=============');

      // Test: See which stylesheets were disabled
      for (let sheet of sheets) {
        console.log(sheet.disabled);
      }
    }

    let nodeList = document.querySelectorAll('.link-to-remove');
    let htmlCol = document.getElementsByClassName('link-to-remove');

    document.querySelector('a').onclick = function(e) {
      nodeList.forEach(link => link.remove());

      console.log('=========STYLESHEET QTY===========');

      // Test: Check how many stylesheets there are
      console.log('This page has ' + htmlCol.length + ' stylesheets with the className: .link-to-remove');

      console.log('=============All CLASS=============');

      // Test: View each all link.class

      for (let tag of htmlCol) {
        console.log(tag.className);
      }
    }
  </script>
</body>

</html>