繁体   English   中英

用某些 class 替换所有元素

[英]Replace all elements with certain class

如果用户在手机上浏览,我试图用 class 'section-heading' with a button替换所有div元素。 我编写的代码仅用所述 class 替换了div的第一个实例,但保留了其余的:

  sectionHeadings = document.getElementsByClassName("section-heading");
  for(i = 0; i < sectionHeadings.length; i++){
    divToReplace = sectionHeadings[i]; 
    btn = document.createElement('button');
    btnText = sectionHeadings[i].innerHTML;
    btn.innerHTML = btnText;
    divToReplace.parentNode.replaceChild(btn, divToReplace);
  }

html 的片段:

<div class="section-heading" id="appetizers">Appetizers</div>
<div class="section-heading" id="soups">Soups</div>

不知道为什么我的循环只是用一个button替换第一个元素,提前感谢您的帮助。

我修复了您的代码的一些问题,现在它可以工作了(:

 [...document.getElementsByClassName("section-heading")].forEach((h) => { const btn = document.createElement('button'); const btnText = h.innerHTML; btn.innerHTML = btnText; h.parentNode.replaceChild(btn, h); });
 <div class="section-heading" id="appetizers">Appetizers</div> <div class="section-heading" id="soups">Soups</div>

您应该注意的主要事情是,不要显式初始化变量,而是创建全局变量。

但它不起作用的主要原因是,正如 junvar 指出的那样,您正在处理一个活动nodeList

 sectionHeadings = document.getElementsByClassName("section-heading"); [...sectionHeadings].forEach((elem)=>{ let btn = document.createElement('button'); btn.innerHTML = elem.innerHTML; elem.outerHTML = btn.outerHTML; });
 <div class="section-heading" id="appetizers">Appetizers</div> <div class="section-heading" id="soups">Soups</div>

问题是getElementsByClassName返回一个实时列表; 即当元素改变时它会更新。 在您的情况下,您将.section-heading元素替换为没有 class .section-heading的按钮,因此每次迭代都会将sectionHeadings的长度减少 1。 您可以通过在replaceChild调用后添加一个console.log(sectionHeadings)来查看这一点。

简单的解决方案是使用扩展运算符将secxtionHeadings转换为非实时数组。

 let sectionHeadings = [...document.getElementsByClassName("section-heading")]; for (i = 0; i < sectionHeadings.length; i++) { divToReplace = sectionHeadings[i]; btn = document.createElement('button'); // btn.classList.add('section-heading'); // This would also solve the issue, but could have unintended side-effects. btnText = sectionHeadings[i].innerHTML; btn.innerHTML = btnText; divToReplace.parentNode.replaceChild(btn, divToReplace); console.log(i, sectionHeadings.length, sectionHeadings) }
 <div class="section-heading" id="appetizers">Appetizers</div> <div class="section-heading" id="soups">Soups</div>

Document.getElementsByClassName()方法返回一个实时的HTMLCollection 该集合反映页面上元素的当前状态,并在添加或删除具有 class 的元素时自动更改。 当您将第一个div替换为button时,您使用 class .section-heading删除一个元素,并且下一个项目成为第一个,但由于循环已经处理了第一个项目( i = 0 ),它将被跳过。

不要使用返回实时集合的方法,而是使用Document.querySelectorAll() ,它会生成 staticNodeList 然后使用NodeList.forEach()迭代节点列表,并替换它们:

 document.querySelectorAll('.section-heading').forEach(divToReplace => { const btn = document.createElement('button'); btn.innerHTML = divToReplace.innerHTML; divToReplace.parentNode.replaceChild(btn, divToReplace); })
 <div class="section-heading" id="appetizers">Appetizers</div> <div class="section-heading" id="soups">Soups</div>

根据getElementsByClassName返回一个将更新的实时列表,我认为您只需要始终替换此列表的第一个元素,如下所示

  sectionHeadings = document.getElementsByClassName("section-heading");
  while(sectionHeadings.length > 0){
    divToReplace = sectionHeadings[0]; 
    btn = document.createElement('button');
    btnText = sectionHeadings[0].innerHTML;
    btn.innerHTML = btnText;
    divToReplace.parentNode.replaceChild(btn, divToReplace);
  }
<div class="section-heading" id="appetizers">Appetizers</div>
<div class="section-heading" id="soups">Soups</div>

我提出以下解决方案:

[...document.getElementsByClassName('section-heading')].forEach(divToReplace => {
  const btn = document.createElement('button');
  btn.innerHTML = divToReplace.innerHTML;
  divToReplace.replaceWith(btn);
});
  1. 将 nodeList 转换为数组 - [...document.getElementsByClassName('section-heading')]
  2. forEach(divToReplace - 循环抛出每个项目
  3. divToReplace.replaceWith(btn); - 用 btn 替换当前数组项

这个解决方案更好,因为它不需要遍历 DOM 来查找父子节点。

暂无
暂无

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

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