[英]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);
});
这个解决方案更好,因为它不需要遍历 DOM 来查找父子节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.