用文本节点替换<span>仅生效一次:是代码问题还是浏览器问题?
问题:替换HTML占位符仅第一个生效的原因?
我尝试替换HTML中形如<span id="Something" />的占位符时遇到问题:
- 使用第一段JavaScript代码时,仅能替换第一个匹配项,后续无法定位下一个匹配元素;
- 改用设置
innerText的第二段代码则可完成全部替换。
第一段(仅替换第一个):
function set_placeholder(cls, txt) { txt = document.createTextNode(txt); for (var e of document.getElementsByClassName(cls)) { e.parentNode.replaceChild(txt, e); } }
第二段(全部替换):
function set_placeholder(cls, txt) { for (var e of document.getElementsByClassName(cls)) { e.innerText = txt; } }
示例HTML中ph-customer-date类出现两次,调用set_placeholder('ph-customer-date', '30.12.2023')仅替换第一个。想知道是代码问题还是Firefox 102的浏览器问题?
解答
这是代码逻辑问题,和Firefox 102浏览器无关,核心原因是重复使用同一个DOM节点:
- 第一段代码里,
document.createTextNode(txt)只执行了一次,生成的是单个文本节点。DOM节点在文档树中只能存在一个位置,第一次替换时这个节点被插入到第一个元素的位置;第二次循环尝试替换时,相当于把这个节点从第一个位置移动到第二个位置,而不是创建新节点。最终看起来只有第一个被替换(实际是节点被移走,第一个位置变成空,第二个位置有文本)。 - 第二段代码中,
e.innerText = txt会自动为每个元素生成独立的文本节点,每个元素都有自己的文本内容,所以所有匹配项都能被正确替换。
修复第一段代码的方案
把创建文本节点的操作放到循环内部,每次循环生成新的文本节点:
function set_placeholder(cls, txt) { for (var e of document.getElementsByClassName(cls)) { const textNode = document.createTextNode(txt); e.parentNode.replaceChild(textNode, e); } }
内容的提问来源于stack exchange,提问作者U. Windl
相关产品推荐
相关产品推荐

