未捕获的类型错误:无法读取未定义的属性“包含”
<块引用>未捕获的类型错误:无法设置未定义的属性“显示”
我正在尝试遍历 todoList 并获取子元素。我错在哪里?子元素是列表项。列表项在添加待办事项时动态添加。
const todoInput = document.querySelector('.todo-input');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector(".filter-todo");
const todoButton = document.querySelector(".todo-button");
todoButton.addEventListener("click", addTodo);
filterOption.addEventListener("click", filterTodo);
function addTodo(e) {
e.preventDefault();
console.log("hello");
//todo div
const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");
//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item')
todoDiv.appendChild(newTodo);
//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML = '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);
//append to list
todoList.appendChild(todoDiv)
//clear todo input value
todoInput.value = "";
}
function filterTodo(e) {
const todos = todoList.childNodes;
todos.forEach(function(todo) {
console.log(todo);
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";
}
}
});
}
.todo-container {
display: flex;
justify-content: center;
align-items: center;
}
.todo-list {
min-width: 30%;
list-style: none;
}
.todo {
margin: 0.5rem;
background: white;
color: black;
font-size: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.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);
}
.todo-item {
padding: 0rem 0.5rem;
}
.fa-trash,
.fa-check {
pointer-events: none;
}
.completed {
text-decoration: line-through;
opacity: 0.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://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<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">
<!---Adding todos dynamically-->
</ul>
</div>
答案 0 :(得分:0)
很多东西要重写
我添加了完成和删除功能
const todoInput = document.querySelector('.todo-input');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector(".filter-todo");
const todoButton = document.querySelector(".todo-button");
todoButton.addEventListener("click", addTodo);
filterOption.addEventListener("change", filterTodo);
todoList.addEventListener("click", handleTodo)
function handleTodo(e) {
const tgt = e.target.closest("button");
if (tgt) {
if (tgt.classList.contains("complete-btn")) {
tgt.closest("div").classList.add("completed");
} else if (tgt.classList.contains("trash-btn")) {
tgt.closest("div").remove();
}
}
}
function addTodo(e) {
e.preventDefault();
console.log("hello");
//todo div
const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");
//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item')
todoDiv.appendChild(newTodo);
//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML = '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);
//append to list
todoList.appendChild(todoDiv)
//clear todo input value
todoInput.value = "";
}
function filterTodo(e) {
const todos = todoList.querySelectorAll(".todo-list div");
const val = e.target.value;
todos.forEach(function(todo) {
const show = val === "all" ||
(val === "completed" && todo.classList.contains("completed")) ||
(val === "uncompleted" && !todo.classList.contains("completed"));
todo.classList.toggle("hide", !show)
});
}
.todo-container {
display: flex;
justify-content: center;
align-items: center;
}
.todo-list {
min-width: 30%;
list-style: none;
}
.todo {
margin: 0.5rem;
background: white;
color: black;
font-size: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.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);
}
.todo-item {
padding: 0rem 0.5rem;
}
.fa-trash,
.fa-check {
pointer-events: none;
}
.completed {
text-decoration: line-through;
opacity: 0.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;
}
.hide {
display: none
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<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">
<!---Adding todos dynamically-->
</ul>
</div>
答案 1 :(得分:0)
const todoInput = document.querySelector('.todo-input');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector(".filter-todo");
const todoButton = document.querySelector(".todo-button");
todoButton.addEventListener("click", addTodo);
filterOption.addEventListener("click", filterTodo);
function addTodo(e) {
e.preventDefault();
console.log("hello");
//todo div
const todoDiv = document.createElement("div");
todoDiv.classList.add("todo");
//create li
const newTodo = document.createElement('li');
newTodo.innerText = todoInput.value;
newTodo.classList.add('todo-item')
todoDiv.appendChild(newTodo);
//check mark button
const completedButton = document.createElement('button');
completedButton.innerHTML = '<i class="fas fa-check"></i>';
completedButton.classList.add("complete-btn");
todoDiv.appendChild(completedButton);
//check trash button
const trashButton = document.createElement('button');
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
todoDiv.appendChild(trashButton);
//append to list
todoList.appendChild(todoDiv)
//clear todo input value
todoInput.value = "";
}
function filterTodo(e) {
const todos = todoList.childNodes;
todos.forEach(function(todo) {
console.log(todo);
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";
}
}
});
}
.todo-container {
display: flex;
justify-content: center;
align-items: center;
}
.todo-list {
min-width: 30%;
list-style: none;
}
.todo {
margin: 0.5rem;
background: white;
color: black;
font-size: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.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);
}
.todo-item {
padding: 0rem 0.5rem;
}
.fa-trash,
.fa-check {
pointer-events: none;
}
.completed {
text-decoration: line-through;
opacity: 0.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://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" />
<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>