如何使用 JavaScript 修复 "toggle" a "classList"
How to fix "toggle" a "classList" using JavaScript
我有一个要添加的列表 class,但只有通过输入添加后的项目才能使用切换。代码中的项目不起作用。
我想知道是否也与“这个”有关属性。
Link 到 CodePen。
https://codepen.io/kennedyrmenezes/pen/BaQRXMq
li.addEventListener("click", function() {
var finished = this.classList.toggle("done");
var removeButton = document.createElement("button");
removeButton.classList.add("deleteButton");
if (finished) {
removeButton.appendChild(document.createTextNode("remove"));
removeButton.classList = "deleteButton";
li.appendChild(removeButton);
removeButton.addEventListener("click", function() {
this.parentElement.remove();
});
} else {
this.getElementsByClassName("deleteButton")[0].remove();
}
})
那是因为您只监听 click
动态添加的 li
元素的事件。
您还应该为硬编码元素添加事件侦听器。在下面的示例中,当单击 li
项
时,我会显示警报
document.querySelectorAll('li').forEach(liItem => {
liItem.addEventListener("click", function() {
alert('click');
});
})
如果查看您编写的代码,您只是将事件处理程序附加到新创建的 li
节点。
要绕过它,您可以在页面加载时将事件处理程序附加到所有现有的 li
元素,或者您可以使用 event delegation 的概念绑定事件处理程序一次。我发现第二种方法更简洁,因为您不必担心在将新的 li
元素添加到 DOM
.
后添加处理程序
我在您的代码中发现了以下问题。
- 没有将点击处理程序附加到现有
li
元素。
- 在删除
li
或 button
时不删除它们的点击处理程序(这可能会导致应用程序内存泄漏)。
var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var $body = document.querySelector('body');
// attach event handlers using event delegation.
function removeButtonHandler() {
this.parentElement.remove();
}
$body.addEventListener('click', function(e) {
const $target = e.target;
// if target is not li, do nothing
if ($target.tagName !== 'LI') {
return;
}
var finished = $target.classList.toggle("done");
var removeButton = document.createElement("button");
removeButton.classList.add("deleteButton");
if (finished) {
removeButton.appendChild(document.createTextNode("remove"));
removeButton.classList = "deleteButton";
$target.appendChild(removeButton);
removeButton.addEventListener("click", removeButtonHandler);
} else {
var $liRemoveButton = $target.querySelector('button');
if($liRemoveButton) {
// Also remove the handler for the delete button
$liRemoveButton.removeEventListener("click", removeButtonHandler);
$target.removeChild($liRemoveButton);
}
}
});
function inputLength() {
return input.value.length;
}
function creatListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
ul.appendChild(li);
input.value = "";
}
function addListAfterClick() {
if (inputLength() > 0) {
creatListElement();
}
}
function addListAfterKeypress(event) {
if (inputLength() > 0 && event.keyCode === 13) {
creatListElement();
}
}
button.addEventListener("click", addListAfterClick);
input.addEventListener("keypress", addListAfterKeypress);
li {
color: black;
}
h1,
p {
color: black;
}
button {
color: white;
background: #1C3144;
padding: 10px;
border-radius: 3px;
border-style: none;
}
input {
border-radius: 3px;
padding: 10px;
}
.testingIt {
text-decoration-line: line-through;
}
.deleteButton {
background-color: #A31420;
color: #fff;
border-radius: 3px;
margin: 20px;
border-style: none;
}
.done {
text-decoration: line-through #A31420;
}
<body>
<h1>Shopping List</h1>
<p id="first">Get it done today</p>
<input id="userinput" type="text" placeholder="enter items">
<button id="enter">Enter</button>
<ul>
<li>Notebook</li>
<li>Jello</li>
<li>Spinach</li>
<li>Rice</li>
<li>Birthday cake</li>
<li>Candles</li>
</ul>
</body>
我有一个要添加的列表 class,但只有通过输入添加后的项目才能使用切换。代码中的项目不起作用。
我想知道是否也与“这个”有关属性。
Link 到 CodePen。
https://codepen.io/kennedyrmenezes/pen/BaQRXMq
li.addEventListener("click", function() {
var finished = this.classList.toggle("done");
var removeButton = document.createElement("button");
removeButton.classList.add("deleteButton");
if (finished) {
removeButton.appendChild(document.createTextNode("remove"));
removeButton.classList = "deleteButton";
li.appendChild(removeButton);
removeButton.addEventListener("click", function() {
this.parentElement.remove();
});
} else {
this.getElementsByClassName("deleteButton")[0].remove();
}
})
那是因为您只监听 click
动态添加的 li
元素的事件。
您还应该为硬编码元素添加事件侦听器。在下面的示例中,当单击 li
项
document.querySelectorAll('li').forEach(liItem => {
liItem.addEventListener("click", function() {
alert('click');
});
})
如果查看您编写的代码,您只是将事件处理程序附加到新创建的 li
节点。
要绕过它,您可以在页面加载时将事件处理程序附加到所有现有的 li
元素,或者您可以使用 event delegation 的概念绑定事件处理程序一次。我发现第二种方法更简洁,因为您不必担心在将新的 li
元素添加到 DOM
.
我在您的代码中发现了以下问题。
- 没有将点击处理程序附加到现有
li
元素。 - 在删除
li
或button
时不删除它们的点击处理程序(这可能会导致应用程序内存泄漏)。
var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var $body = document.querySelector('body');
// attach event handlers using event delegation.
function removeButtonHandler() {
this.parentElement.remove();
}
$body.addEventListener('click', function(e) {
const $target = e.target;
// if target is not li, do nothing
if ($target.tagName !== 'LI') {
return;
}
var finished = $target.classList.toggle("done");
var removeButton = document.createElement("button");
removeButton.classList.add("deleteButton");
if (finished) {
removeButton.appendChild(document.createTextNode("remove"));
removeButton.classList = "deleteButton";
$target.appendChild(removeButton);
removeButton.addEventListener("click", removeButtonHandler);
} else {
var $liRemoveButton = $target.querySelector('button');
if($liRemoveButton) {
// Also remove the handler for the delete button
$liRemoveButton.removeEventListener("click", removeButtonHandler);
$target.removeChild($liRemoveButton);
}
}
});
function inputLength() {
return input.value.length;
}
function creatListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
ul.appendChild(li);
input.value = "";
}
function addListAfterClick() {
if (inputLength() > 0) {
creatListElement();
}
}
function addListAfterKeypress(event) {
if (inputLength() > 0 && event.keyCode === 13) {
creatListElement();
}
}
button.addEventListener("click", addListAfterClick);
input.addEventListener("keypress", addListAfterKeypress);
li {
color: black;
}
h1,
p {
color: black;
}
button {
color: white;
background: #1C3144;
padding: 10px;
border-radius: 3px;
border-style: none;
}
input {
border-radius: 3px;
padding: 10px;
}
.testingIt {
text-decoration-line: line-through;
}
.deleteButton {
background-color: #A31420;
color: #fff;
border-radius: 3px;
margin: 20px;
border-style: none;
}
.done {
text-decoration: line-through #A31420;
}
<body>
<h1>Shopping List</h1>
<p id="first">Get it done today</p>
<input id="userinput" type="text" placeholder="enter items">
<button id="enter">Enter</button>
<ul>
<li>Notebook</li>
<li>Jello</li>
<li>Spinach</li>
<li>Rice</li>
<li>Birthday cake</li>
<li>Candles</li>
</ul>
</body>