开发者问题收集

识别已创建元素的 classList JS

2020-05-02
264

我正在做一个待办事项列表,但在筛选待办事项列表项时卡住了。我甚至不知道问题出在哪里。

我创建了一个列表项,当单击复选图标时,我向其中添加了一个“完成”类,并在另一个函数中迭代列表 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";
                }
```


2个回答

并非所有子节点都是 元素 ,有些是文本节点或评论节点或类似的节点。只有元素具有 样式 属性。

您可能想要 儿童 而不是 childnodes 儿童 只是儿童元素,跳过其他类型的节点。但是请注意,正式, a>您从 儿童 没有 foreach (尽管在某些实现中确实如此)。 ( nodelist 您得到从 childnodes 定义为具有 foreach ,并且可靠地在现代浏览器上使用[仅]。代码>,但随后检查 node.nodetype === node.element_node 在寻找 style 属性之前。


,您可以在 htmlCollection 上polyfill foreach (以及 nodelist on ntery nesty nesty nestive );我描述了如何做 在此答案中

T.J. Crowder
2020-05-02

我在你的代码中发现了几个问题。你可以查看我的解决方案。

我使用了 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>
Sifat Haque
2020-05-02