JavaScript中Text nodes合并异常求助:仅循环末尾段落生效
问题原因与修复方案
嘿,这个问题的核心原因其实很简单:DOM中的每个节点(包括文本节点)在文档树里只能存在一个位置!
你一开始只创建了一个robert文本节点,先把它加到了<h3>里,之后在循环里又反复调用friend1p.appendChild(robert)——但这个操作并不是复制节点,而是把这个唯一的robert节点从它当前所在的位置(比如之前的<p>或者<h3>)移动到新的<p>元素里。所以循环执行到最后,robert只会停留在最后一个<p>(也就是i=1的那个段落)里,前面所有的<p>自然就看不到它啦。
问题现象回顾
从你提供的截图可以看到:

修复方案(两种可选)
方案1:每次需要时创建新的Robert文本节点
既然一个节点不能复用,那我们每次需要插入"Robert"的时候,就创建一个新的文本节点就行。可以把创建逻辑直接放到循环里的对应位置:
document.addEventListener('DOMContentLoaded', function() { var sing = document.getElementById('sing'); sing.addEventListener('click', function() { var friend1 = document.createElement('div'); friend1.className = "friend"; var friend1h3 = document.createElement('h3'); // 保留h3里的Robert friend1h3.appendChild(document.createTextNode('Robert')); document.body.appendChild(friend1h3); for (var i = 99; i > 0; i--) { var friend1p = document.createElement('p'); if (i > 2) { var a = document.createTextNode((i) + " lines of code in the file, " + (i) + " lines of code; "); friend1p.appendChild(a); // 每次创建新的Robert节点 friend1p.appendChild(document.createTextNode('Robert')); var b = document.createTextNode(" strikes one out, clears it all out " + (i - 1) + " lines of code in the file"); friend1p.appendChild(b); } else if (i === 2) { var c = document.createTextNode("2 lines of code in the file, 2 lines of code; "); friend1p.appendChild(c); friend1p.appendChild(document.createTextNode('Robert')); var d = document.createTextNode(" strikes one out, clears it all out 1 line of code in the file"); friend1p.appendChild(d); } else { var e = document.createTextNode("1 line of code in the file, 1 line of code; "); friend1p.appendChild(e); friend1p.appendChild(document.createTextNode('Robert')); var f = document.createTextNode(" strikes one out, clears it all out, 0 lines of code in the file"); friend1p.appendChild(f); } document.body.appendChild(friend1p); } }) })
方案2:复制已有的Robert节点
如果你想保留最初创建的robert节点,也可以用cloneNode(true)方法复制它的副本(因为文本节点是叶子节点,true和false效果一样,但推荐用true保持一致性):
document.addEventListener('DOMContentLoaded', function() { var sing = document.getElementById('sing'); sing.addEventListener('click', function() { var friend1 = document.createElement('div'); friend1.className = "friend"; var friend1h3 = document.createElement('h3'); var robert = document.createTextNode('Robert'); friend1h3.appendChild(robert); document.body.appendChild(friend1h3); for (var i = 99; i > 0; i--) { var friend1p = document.createElement('p'); if (i > 2) { var a = document.createTextNode((i) + " lines of code in the file, " + (i) + " lines of code; "); friend1p.appendChild(a); // 复制robert节点的副本插入 friend1p.appendChild(robert.cloneNode(true)); var b = document.createTextNode(" strikes one out, clears it all out " + (i - 1) + " lines of code in the file"); friend1p.appendChild(b); } else if (i === 2) { var c = document.createTextNode("2 lines of code in the file, 2 lines of code; "); friend1p.appendChild(c); friend1p.appendChild(robert.cloneNode(true)); var d = document.createTextNode(" strikes one out, clears it all out 1 line of code in the file"); friend1p.appendChild(d); } else { var e = document.createTextNode("1 line of code in the file, 1 line of code; "); friend1p.appendChild(e); friend1p.appendChild(robert.cloneNode(true)); var f = document.createTextNode(" strikes one out, clears it all out, 0 lines of code in the file"); friend1p.appendChild(f); } document.body.appendChild(friend1p); } }) })
额外优化建议
你可以把重复的逻辑抽出来,减少代码冗余,比如不管i的值是多少,结构都是「前缀文本」+「Robert」+「后缀文本」,可以这样简化:
document.addEventListener('DOMContentLoaded', function() { var sing = document.getElementById('sing'); sing.addEventListener('click', function() { var friend1h3 = document.createElement('h3'); friend1h3.appendChild(document.createTextNode('Robert')); document.body.appendChild(friend1h3); for (var i = 99; i > 0; i--) { var friend1p = document.createElement('p'); // 生成前缀文本 var prefix = i > 1 ? `${i} lines of code in the file, ${i} lines of code; ` : `1 line of code in the file, 1 line of code; `; // 生成后缀文本 var suffix = i > 1 ? ` strikes one out, clears it all out ${i - 1} ${i-1 > 1 ? 'lines' : 'line'} of code in the file` : ` strikes one out, clears it all out, 0 lines of code in the file`; // 组装段落内容 friend1p.appendChild(document.createTextNode(prefix)); friend1p.appendChild(document.createTextNode('Robert')); friend1p.appendChild(document.createTextNode(suffix)); document.body.appendChild(friend1p); } }) })
这样代码更简洁,也更容易维护~
内容的提问来源于stack exchange,提问作者cDub
相关产品推荐
相关产品推荐

