Javascript for循环每隔一次就工作一次

Javascript for loop works every other time

本文关键字:一次 工作 for 循环 Javascript      更新时间:2023-09-26

所以基本上我在做一个任务列表来练习使用纯Javascript。我不想使用Jquery。最后,我想用Jquery重新创建它。

我当前的问题是,当我在第43行(jsfiddle)上运行for循环时,它只在我想要打开和关闭所有复选框时删除每个其他复选框。抱歉,如果我的代码是混乱的理解。这是我第一次尝试创造这么复杂的东西。

function editItem() {
var findSpanBoxes = document.getElementsByClassName("spanBox");
var findTextBoxes = document.getElementsByClassName("list-item");
var btnDelete = document.createElement("span");
var btnSave = document.getElementsByClassName("save");
if (btnSave.length >= 1) {
    alert("Please save all items first.");
} else if (clicked == 0) {
    clicked = 1;
    for (i = 0; i < findSpanBoxes.length; i++) {
        findSpanBoxes[i].innerHTML = '<input class="box" type="checkbox"></input>';
        btnDelete.innerHTML = '<button class="button">Delete</button>';
        // findTextBoxes[i].appendChild(btnDelete);
    }
} else {
    clicked = 0;
    debugger;
    // **** Problem *****
    for (x = 0; x < findSpanBoxes.length; x++) {
        var box = document.getElementsByClassName("box")[x];
        box.parentNode.removeChild(box);
        console.log(x);
    }
}
}

要查看我的问题,添加几个项目,保存每个项目,然后单击编辑几次。

http://jsfiddle.net/whsn1bom/31/

请留下任何建议/评论!谢谢你!

因为当你删除项目时,其他项目会向下移动一个。这是一个现场收藏。向后循环或使用while循环

for (var x = findSpanBoxes.length-1 x>=0; x--) {

var boxes = document.getElementsByClassName("box");
while (boxes.length) {
    var box = boxes[0];
    box.parentNode.removeChild(box);
}

是否检查了控制台的错误?

Uncaught TypeError: Cannot read property 'parentNode' of undefined

问题是你在循环中调用document.getElementsByClassName("box")。为什么这是一个问题?你也在移除循环中的元素。每次删除一个项时,document.getElementsByClassName("box")数组都会变得更短,因为它只返回在执行时存在的项(并且在调用之间删除项)。

为了帮助解释这一点,可以这样想。第一次通过循环时,删除.box的第一个索引。然后,在下一次迭代中,创建一个新数组,并删除第二个索引。因此,您刚刚跳过了一个方框。

所以,为了解决这个问题,你可以总是删除数组的第一个索引。

var box = document.getElementsByClassName("box")[0];

或者,您可以获得父对象,并以这种方式删除.box元素。

var box_parent = document.getElementsByClassName("spanBox")[x];
box_parent.removeChild(box_parent.firstChild);

这一行有逻辑缺陷

for (x = 0; x < findSpanBoxes.length; x++) {

将迭代更改为以下内容,它将工作

for (x = findSpanBoxes.length-1; x >=0; x--) {

这是因为当您从列表中删除子项item时,每个元素的索引都会减1。通过从列表末尾(即在最高索引处)删除项,其余项的索引不会改变。

例如,假设您有项目(index 0 = A, index 1 = B; index 3 = C; index 4 = D).

  • 第一个循环(x=0)删除项目0 (A),新列表变成(index 0 = B, index 1 = C; index 2 = D)。删除第一个元素会导致其余项的索引发生变化。
  • 第一个循环(x=1)删除项目1,即c。注意,B被跳过,因为它的索引从1变为0。

正如epascarelo的回答所暗示的那样,getElementsByClassName返回一个HTMLCollection,这是一个实时集合;对DOM的更改会自动并立即反映在DOM中。

正如他的回答所说,向后遍历数组避免了从DOM中删除项的副作用。另一个解决方案是将类数组的HTMLCollection转换为数组:

var boxes = [].slice.call(document.getElementsByClassName("box"));

这将使boxes成为一个真正的数组,而不是一个活动的类似数组的对象。对DOM的更新不会改变数组的长度,因此您仍然可以向前迭代数组。

如果你正在使用转译器或者只针对支持ES6的浏览器,你可以使用扩展操作符将数组转换缩短为:

var boxes = [...document.getElementsByClassName("box")];