带有复选框的删除功能和 JS 无法正常工作
Delete function with checkbox and JS doesn't work properly
目前我正在制作自己的项目,但遇到了问题。我为 Select/Unselect/Delete 复选框(包括其祖父元素(.layout))编写了如下代码。
然而,不知何故它只工作了 50%。当我创建很多复选框并尝试 select 或取消 select 它们时,它工作得很好。但是,如果我在 select 将它们全部删除后尝试删除它们,它只会删除其中的一半,然后我再次单击它,它会删除剩下的一半,然后一遍又一遍地执行此操作,直到只剩下一个复选框。这不是我遇到的唯一问题。当只有一个复选框时,我无法 select、unselect 或使用我制作的按钮将其删除。你能告诉我我的代码有什么问题以及如何解决吗?
//P.S 下面的代码只是我总结代码的一部分,所以我可以向您展示我的问题的确切部分。如果您需要完整的代码,请给我发消息,我会告诉您:)
谢谢。
const selectAll = document.querySelector(".select");
const unselectAll = document.querySelector(".unselect");
const deleteIndex = document.querySelector(".delete");
selectAll.addEventListener("click", selectAllindex);
unselectAll.addEventListener("click", unselectAllindex);
deleteIndex.addEventListener("click", deleteDiaryIndex);
function selectAllindex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
console.log(testform.checkboxchild.length);
testform.checkboxchild[i].checked = true;
}
}
function unselectAllindex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
testform.checkboxchild[i].checked = false;
}
}
function deleteDiaryIndex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
if (testform.checkboxchild[i].checked) {
removeDiv(testform.checkboxchild[i]);
}
}
}
function removeDiv(d) {
console.log(d.parentElement.parentElement);
d.parentElement.remove();
}
.trash{
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./test.css" />
</head>
<body>
<form action="" name="testform" class="test">
<div class="divs">
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
</div>
<div class="buttons">
<button class="selector select" value="selectall">Select All</button>
<button class="selector unselect" value="unselectall">
Unselect All
</button>
<button class="selector delete" value="delete">Delete</button>
</div>
</form>
<script src="./test.js"></script>
</body>
</html>
if I try to delete them after selecting them all, it only deletes half of them, and I click it again, and it deletes half of them remain and do this over and over until only one checkbox is left.
发生这种情况是因为您在遍历它时改变 DOM 个节点 testform.checkboxchild
的 。
function deleteDiaryIndex(i) {
i.preventDefault();
console.log(testform.checkboxchild instanceof HTMLCollection); // false
console.log(testform.checkboxchild instanceof NodeList); // true
console.log(Object.prototype.toString.call(testform.checkboxchild));
// '[object RadioNodeList]' (in both Chrome and Firefox, strangely)
for (i = 0; i < testform.checkboxchild.length; i++) {
if (testform.checkboxchild[i].checked) {
removeDiv(testform.checkboxchild[i]);
}
}
}
这个 table 试图展示当所有复选框都被选中时,在上述函数中迭代时会发生什么。
i = 0
i = 1
i = 2
1st checkBox is
checkboxchild[0]
removed
2nd checkBox is
checkboxchild[1]
checkboxchild[0]
checkboxchild[0]
3rd checkBox is
checkboxchild[2]
checkboxchild[1]
removed
4th checkBox is
checkboxchild[3]
checkboxchild[2]
checkboxchild[1]
checkboxchild.length
4
3
2
只有两个复选框被删除,因为 length
和 testform.checkboxchild
的索引在从 DOM 中删除每个复选框后会自动更新,所以什么是索引删除的复选框成为集合中下一个复选框的索引。
例如,第二个复选框没有被删除,因为在循环的第二次迭代中,当 i = 1
、checkboxchild[1]
指向第三个复选框,而不是第二个!
另请注意,当 i
变为 2
时循环结束,因为它不小于长度,即删除两个复选框后的 2
。
上述问题的一个解决方案是在迭代之前将活动集合转换为普通数组,例如
const checkboxes = Array.from(testform.checkboxchild);
另一种解决方案是根本不使用 testform.checkboxchild
,而是使用 querySelectorAll
,其中 returns 是节点的静态列表而不是实时节点列表。
const checkboxes = document.querySelectorAll('input[type=checkbox]');
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
removeDiv(checkboxes[i]);
}
}
}
或
const checkedboxes = document.querySelectorAll('input[type=checkbox]:checked');
for (const cb of checkedboxes) {
removeDiv(cb);
}
您可能还想考虑使用 display: none
或 visibility: hidden
样式作为从文档中完全删除复选框的一种易于逆转的替代方法。
When there is only a single checkbox, I can not select, unselect, or delete it with buttons I made
这是使用 testform.checkboxchild
引用复选框的另一个问题。
如果只剩下一个复选框,那么 testform.checkboxchild
将指向单个复选框而不是一个复选框列表,因此它不会有 length
属性 并且是可迭代的.
一个简单的解决方案是先检查 length
属性 是否存在。例如
function selectAllindex(event) {
event.preventDefault();
if (testform.checkboxchild.length !== undefined) {
for (let i = 0; i < testform.checkboxchild.length; i++) {
testform.checkboxchild[i].checked = true;
}
} else {
testform.checkboxchild.checked = true;
}
}
或
function selectAllindex(event) {
event.preventDefault();
const checkboxes = document.querySelectorAll('input[type=checkbox]');
for (const cb of checkboxes) {
cb.checked = true;
}
}
我的建议是:不要使用 testform.checkboxchild
来引用复选框。
目前我正在制作自己的项目,但遇到了问题。我为 Select/Unselect/Delete 复选框(包括其祖父元素(.layout))编写了如下代码。
然而,不知何故它只工作了 50%。当我创建很多复选框并尝试 select 或取消 select 它们时,它工作得很好。但是,如果我在 select 将它们全部删除后尝试删除它们,它只会删除其中的一半,然后我再次单击它,它会删除剩下的一半,然后一遍又一遍地执行此操作,直到只剩下一个复选框。这不是我遇到的唯一问题。当只有一个复选框时,我无法 select、unselect 或使用我制作的按钮将其删除。你能告诉我我的代码有什么问题以及如何解决吗?
//P.S 下面的代码只是我总结代码的一部分,所以我可以向您展示我的问题的确切部分。如果您需要完整的代码,请给我发消息,我会告诉您:)
谢谢。
const selectAll = document.querySelector(".select");
const unselectAll = document.querySelector(".unselect");
const deleteIndex = document.querySelector(".delete");
selectAll.addEventListener("click", selectAllindex);
unselectAll.addEventListener("click", unselectAllindex);
deleteIndex.addEventListener("click", deleteDiaryIndex);
function selectAllindex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
console.log(testform.checkboxchild.length);
testform.checkboxchild[i].checked = true;
}
}
function unselectAllindex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
testform.checkboxchild[i].checked = false;
}
}
function deleteDiaryIndex(i) {
i.preventDefault();
for (i = 0; i < testform.checkboxchild.length; i++) {
if (testform.checkboxchild[i].checked) {
removeDiv(testform.checkboxchild[i]);
}
}
}
function removeDiv(d) {
console.log(d.parentElement.parentElement);
d.parentElement.remove();
}
.trash{
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./test.css" />
</head>
<body>
<form action="" name="testform" class="test">
<div class="divs">
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
<div class="layout">
<div class="checkboxs">
<input type="checkbox" name="checkboxchild" id="" />
</div>
</div>
</div>
<div class="buttons">
<button class="selector select" value="selectall">Select All</button>
<button class="selector unselect" value="unselectall">
Unselect All
</button>
<button class="selector delete" value="delete">Delete</button>
</div>
</form>
<script src="./test.js"></script>
</body>
</html>
if I try to delete them after selecting them all, it only deletes half of them, and I click it again, and it deletes half of them remain and do this over and over until only one checkbox is left.
发生这种情况是因为您在遍历它时改变 DOM 个节点 testform.checkboxchild
的
function deleteDiaryIndex(i) {
i.preventDefault();
console.log(testform.checkboxchild instanceof HTMLCollection); // false
console.log(testform.checkboxchild instanceof NodeList); // true
console.log(Object.prototype.toString.call(testform.checkboxchild));
// '[object RadioNodeList]' (in both Chrome and Firefox, strangely)
for (i = 0; i < testform.checkboxchild.length; i++) {
if (testform.checkboxchild[i].checked) {
removeDiv(testform.checkboxchild[i]);
}
}
}
这个 table 试图展示当所有复选框都被选中时,在上述函数中迭代时会发生什么。
i = 0 | i = 1 | i = 2 | |
---|---|---|---|
1st checkBox is | checkboxchild[0] | removed | |
2nd checkBox is | checkboxchild[1] | checkboxchild[0] | checkboxchild[0] |
3rd checkBox is | checkboxchild[2] | checkboxchild[1] | removed |
4th checkBox is | checkboxchild[3] | checkboxchild[2] | checkboxchild[1] |
checkboxchild.length | 4 | 3 | 2 |
只有两个复选框被删除,因为 length
和 testform.checkboxchild
的索引在从 DOM 中删除每个复选框后会自动更新,所以什么是索引删除的复选框成为集合中下一个复选框的索引。
例如,第二个复选框没有被删除,因为在循环的第二次迭代中,当 i = 1
、checkboxchild[1]
指向第三个复选框,而不是第二个!
另请注意,当 i
变为 2
时循环结束,因为它不小于长度,即删除两个复选框后的 2
。
上述问题的一个解决方案是在迭代之前将活动集合转换为普通数组,例如
const checkboxes = Array.from(testform.checkboxchild);
另一种解决方案是根本不使用 testform.checkboxchild
,而是使用 querySelectorAll
,其中 returns 是节点的静态列表而不是实时节点列表。
const checkboxes = document.querySelectorAll('input[type=checkbox]');
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
removeDiv(checkboxes[i]);
}
}
}
或
const checkedboxes = document.querySelectorAll('input[type=checkbox]:checked');
for (const cb of checkedboxes) {
removeDiv(cb);
}
您可能还想考虑使用 display: none
或 visibility: hidden
样式作为从文档中完全删除复选框的一种易于逆转的替代方法。
When there is only a single checkbox, I can not select, unselect, or delete it with buttons I made
这是使用 testform.checkboxchild
引用复选框的另一个问题。
如果只剩下一个复选框,那么 testform.checkboxchild
将指向单个复选框而不是一个复选框列表,因此它不会有 length
属性 并且是可迭代的.
一个简单的解决方案是先检查 length
属性 是否存在。例如
function selectAllindex(event) {
event.preventDefault();
if (testform.checkboxchild.length !== undefined) {
for (let i = 0; i < testform.checkboxchild.length; i++) {
testform.checkboxchild[i].checked = true;
}
} else {
testform.checkboxchild.checked = true;
}
}
或
function selectAllindex(event) {
event.preventDefault();
const checkboxes = document.querySelectorAll('input[type=checkbox]');
for (const cb of checkboxes) {
cb.checked = true;
}
}
我的建议是:不要使用 testform.checkboxchild
来引用复选框。