为什么用javascript删除元素会阻止元素的迭代?
我试图用标签替换页面上的所有文本字段为什么用javascript删除元素会阻止元素的迭代?,javascript,html,dom,Javascript,Html,Dom,我试图用标签替换页面上的所有文本字段 function replaceInputTextFieldsWithValues() { var inputFields = document.getElementsByTagName("input"); for(var i = 0; i < inputFields.length; i++) { if(inputFields[i].getAttribute("type")== "text") {
function replaceInputTextFieldsWithValues() {
var inputFields = document.getElementsByTagName("input");
for(var i = 0; i < inputFields.length; i++) {
if(inputFields[i].getAttribute("type")== "text") {
var parent = inputFields[i].parentNode;
var value = inputFields[i].value;
parent.removeChild(inputFields[i]);
var label = document.createElement('label');
label.setAttribute('for', value);
label.innerHTML = value;
parent.appendChild(label);
}
}
}
代码似乎运行良好。为什么会发生这种情况?我如何修复它?您从
getElementsByTagName
得到的是一个活动的。(对于其他getElementsByXYZ
方法也是如此,但对于querySelectorAll
)这意味着如果删除索引0
处的元素,则HTMLCollection
的长度将下降,并且索引0
处将有一个新元素,而不是刚才删除的元素
只要逆向努力,你就会没事的:
for(var i = inputFields.length - 1; i >= 0; i--) {
// ...
}
或者,将HTMLCollection
转换为一个数组,然后在数组中循环。(请参见下面的实时示例和代码)
编辑:或,正如Chris在评论中指出的那样,您可以利用更改的长度
,但这并不像Chris的建议那么简单,因为您有时只是删除元素。它看起来是这样的:
var inputFields = document.getElementsByTagName("input");
var i = 0;
while (i < inputFields.length) {
if(inputFields[i].getAttribute("type")== "text") {
// Remove it and DON'T increment `index`
}
else {
// Skip this one by incrementing `index`
++index;
}
}
JavaScript:
var lilist, liarray;
// Get the HTMLCollection, which is live
lilist = document.getElementsByTagName('li');
// Create an array of its elements
liarray = Array.prototype.slice.call(lilist, 0);
// Show initial length of both
display("lilist.length = " + lilist.length); // Shows 3
display("liarray.length = " + liarray.length); // Shows 3
// Show what the 0th element of both is (both show "LI0" in the live example)
display("lilist[0].innerHTML = " + lilist[0].innerHTML); // Shows LI0
display("liarray[0].innerHTML = " + liarray[0].innerHTML); // Shows LI0
// Remove the first list item
display("Removing item 0");
lilist[0].parentNode.removeChild(lilist[0]);
// Show the length of both, note that the list's length
// has gone down, but the array's hasn't
display("lilist.length = " + lilist.length); // Shows 2, not 3
display("liarray.length = " + liarray.length); // Still shows 3
// Show what the 0th element of both *now* is
display("lilist[0].innerHTML = " + lilist[0].innerHTML); // Shows LI1 now
display("liarray[0].innerHTML = " + liarray[0].innerHTML); // Still shows LI0
或者,如果你不想向后循环,你可以在(inputFields.length>=0)时执行
,
并在循环中始终使用inputFields[0]
。@Chris:这通常是个好主意,但他对是否删除输入有一定的逻辑,因此,他需要一个索引,在跳过时增加,但在删除时没有增加,然后他需要根据长度
进行测试,它变得(稍微)复杂。不是很复杂(我相信我们都做过),但很复杂。“for”属性是指输入字段的id,因此对标签的关注会激活其相关字段。严格来说,没有字段的标签是无效的。删除输入会使系统无需执行任何操作。也许你应该跳过设置for,或者隐藏输入,甚至使用除label之外的其他类型的元素。@kennebec:很好的一点,我必须承认我甚至没有读过那么多@BlackSheep:绝对不要为此使用标签,或者如果不使用其属性。使用带有data val
属性的span或其他东西(带有data-
前缀的自定义属性现在在所有主要浏览器上都可以使用,从HTML5开始)。
<ul>
<li>LI0</li>
<li>LI1</li>
<li>LI2</li>
</ul>
var lilist, liarray;
// Get the HTMLCollection, which is live
lilist = document.getElementsByTagName('li');
// Create an array of its elements
liarray = Array.prototype.slice.call(lilist, 0);
// Show initial length of both
display("lilist.length = " + lilist.length); // Shows 3
display("liarray.length = " + liarray.length); // Shows 3
// Show what the 0th element of both is (both show "LI0" in the live example)
display("lilist[0].innerHTML = " + lilist[0].innerHTML); // Shows LI0
display("liarray[0].innerHTML = " + liarray[0].innerHTML); // Shows LI0
// Remove the first list item
display("Removing item 0");
lilist[0].parentNode.removeChild(lilist[0]);
// Show the length of both, note that the list's length
// has gone down, but the array's hasn't
display("lilist.length = " + lilist.length); // Shows 2, not 3
display("liarray.length = " + liarray.length); // Still shows 3
// Show what the 0th element of both *now* is
display("lilist[0].innerHTML = " + lilist[0].innerHTML); // Shows LI1 now
display("liarray[0].innerHTML = " + liarray[0].innerHTML); // Still shows LI0