识别已创建元素的 classList JS
我正在做一个待办事项列表,但在筛选待办事项列表项时卡住了。我甚至不知道问题出在哪里。
我创建了一个列表项,当单击复选图标时,我向其中添加了一个“完成”类,并在另一个函数中迭代列表 childNotes 并尝试过滤具有该完成类的列表,但一直收到以下错误:
“未捕获的 TypeError:无法在 app.js:84 处设置未定义的属性‘display’。在 NodeList.forEach()处,在 HTMLSelectElement.filterTodo(app.js:76)”即使列表有列表项
代码: https://codepen.io/mullerz/pen/vYNeMEO?editors=1111
if(item.classList[0] === "complete-btn"){
const todo = item.parentElement;
todo.classList.toggle("completed");
}
}
function filterTodo(e){
const todos = todoList.childNodes;
//console.log(todos)
todos.forEach(function(todo, index){
//if(index === 0){return}
console.log({todo})
switch (e.target.value) {
case "all" :
console.log(todo.classList)
todo.style.display = "flex";
break;
case "completed" :
if(todo.classList.contains("completed") ){
console.log(todo.classList)
todo.style.display = "flex";
}
else{
todo.style.display = "none";
}
```
并非所有子节点都是
元素
,有些是文本节点或评论节点或类似的节点。只有元素具有
样式
属性。
您可能想要
儿童
而不是
childnodes
。
儿童
只是儿童元素,跳过其他类型的节点。但是请注意,正式,
(尽管在某些实现中确实如此)。 (
a>您从
foreach儿童
没有
您得到从
nodelist
childnodes
定义为具有
foreach
,并且可靠地在现代浏览器上使用[仅]。代码>,但随后检查
node.nodetype === node.element_node
在寻找
style
属性之前。
,您可以在
htmlCollection
上polyfill
foreach
(以及
nodelist
on ntery nesty nesty nestive
);我描述了如何做
在此答案中
。
我在你的代码中发现了几个问题。你可以查看我的解决方案。
我使用了
change
事件来触发过滤函数,还使用了
const todos = [...todoList.children];
来获取所需的子项。
console.clear();
const todoInput = document.querySelector(".todo-input");
const todoButton = document.querySelector(".todo-button");
const todoList = document.querySelector(".todo-list");
const filterOption = document.querySelector(".filter-todo");
todoButton.addEventListener("click", addTodo)
todoList.addEventListener("click", deleteCheck)
filterOption.addEventListener("change", filterTodo)
function addTodo(e){
e.preventDefault();
// create div that will have the line items of each task
const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");
// create line item
const newTodo = document.createElement("li");
newTodo.innerText = todoInput.value;
newTodo.classList.add("todo-item");
todoDiv.appendChild(newTodo);
// create completion button
const completeButton = document.createElement("button");
completeButton.innerHTML = '<i class="fas fa-check"></i>';
completeButton.classList.add("complete-btn");
todoDiv.appendChild(completeButton);
// create discard button
const trashButton = document.createElement("button");
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);
// attach de div we just created to the existing ul in the html
todoList.appendChild(todoDiv)
// clear
todoInput.value = "";
}
// delete item
function deleteCheck(e){
const item = e.target;
if(item.classList[0] === "trash-btn"){
const todo = item.parentElement;
todo.classList.add("fall");
// check if transition of the class css "fall" has ended and then remove the item
todo.addEventListener("transitionend", function(){
todo.remove();
});
}
// check mark
if(item.classList[0] === "complete-btn"){
const todo = item.parentElement;
todo.classList.toggle("completed");
}
}
function filterTodo(e){
const todos = [...todoList.children];
todos.forEach(function(todo, index){
switch (e.target.value) {
case "all" :
todo.style.display = "flex";
break;
case "completed" :
if(todo.classList.contains("completed") ){
todo.style.display = "flex";
}
else{
todo.style.display = "none";
}
break;
case "uncompleted" :
if(!todo.classList.contains("completed")){
todo.style.display = "flex";
}
else{
todo.style.display = "none";
}
}
})
}
*{
margin:0;
padding:0;
box-sizing: border-box;
}
body{
background-image: linear-gradient(120deg, #f6d365, #fda0a5);
color:white;
font-family: 'Cairo', sans-serif;
min-height:100vh;
}
header{
font-size:1.5rem;
}
header, form{
min-height:20vh;
display:flex;
justify-content: center;
align-items: center;
}
form input, form button{
padding:0.5rem;
font-size:2rem;
border:none;
background: white;
}
form button{
background:#d88771;
color:white;
}
form button:hover{
background:white ;
color:#d88771;
}
.todo-container{
display:flex;
justify-content: center;
align-items: center;
}
.todo-list{
min-width:20%;
list-style:none;
}
.todo{
margin: .5rem;
background: white;
color:black;
font-size:1.5rem;
display:flex;
justify-content: space-between;
align-items:center;
transition: all .5s ease;
}
.todo li{ flex:1; }
.trash-btn, .complete-btn{
background: #ff6f47;
color:white;
border:none;
padding:1rem;
cursor:pointer;
font-size:1rem;
}
.complete-btn{
background:rgb(73, 204, 73);
color:white;
border:none;
padding:1rem;
cursor:pointer;
font-size:1rem;
}
.todo-item{ padding:0rem .5rem; }
.fa-trash, .fa-check{ pointer-events: none; }
.completed{
text-decoration:line-through;
opacity:.5;
}
.fall{
transform: translateY(8rem) rotateZ(20deg);
opacity:0;
}
select{
-webkit-appearance: none;
-moz-appearance: none;
appearance:none;
outline:none;
border:none;
}
.select{
margin: 1rem;
position: relative;
overflow: hidden;
}
select{
color: #ff6f47;
width: 10rem;
cursor: pointer;
padding: 1rem;
}
.select::after{
content: "\25BC";
position:absolute;
background: #ff6f47;
top:0;
right:0;
padding:1rem;
pointer-events:none;
transition: all 0.3s ease;
}
.select:hover::after{
background: white;
color:#ff6f47;
}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.7/css/all.css">
<header>
<h1>To do List</h1>
</header>
<form>
<input type="text" class="todo-input">
<button class="todo-button" type="submit">
<i class="fas fa-plus-square"></i>
</button>
<div class="select">
<select name="todos" class="filter-todo">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
<div class="todo-container">
<ul class="todo-list">
</ul>
</div>