Javascript没有选择后来通过Javascript使用innerHTML添加的html元素



我用JS创建了一个todo列表。我已经附上了相同的代码片段。我在html中有三个硬编码的todo,每个todo都有两个相关的按钮('x'删除todo'y'/strong>标记,其中输入了todo文本,点击回车后,我将使用innerHTML将它们嵌入到html中,同时嵌入动态添加的todo在DOM中可见。但问题是与todo相关联的按钮('x'和'y'(没有按预期工作。此外,我试着调试我的问题,发现按钮("x"one_answers"y"(没有被选中。我不明白为什么会发生这种事。如有任何帮助,我们将不胜感激。

const todoInp = document.querySelector('.add input')
const todos = document.querySelector('.todos')

const remove = document.querySelectorAll('.remove')
const doneBtns = document.querySelectorAll('.check')
todoInp.addEventListener('keyup', (e) => {
if (e.key === 'Enter' && e.target.value !== '') {
const todoVal = e.target.value
const todo = document.createElement('div')
todo.classList.add('todo')
todo.innerHTML = `
<p>${todoVal}</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
`
todos.appendChild(todo)
todoInp.value = ''
}
})



doneBtns.forEach((btn) => {
btn.addEventListener('click', () => {
const mainPar = btn.parentElement.parentElement
mainPar.classList.toggle('done')
})
})
remove.forEach((btn) => {
btn.addEventListener('click', () => {
const parent = btn.parentElement
const mainPar = parent.parentElement
mainPar.remove()
})
})
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0;
padding: 0;
margin-top: 50px;
height: 100vh;
background-color: aliceblue;
}
.container{
width: 600px;
height: auto;
padding: 50px;
}
.add,
.todos{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.add label{
font-family: 'Courier New', Courier, monospace;
font-weight: bold;
color: darkblue;
}
.add input{
background: white;
padding: 13px;
border: 0.5px solid #ccc;
width: 90%;
border-radius: 4px;
}
.add input:focus{
outline: none;
}
.add input::placeholder{
color:#ccc
}
.todo{
color: darkblue;
width: 90%;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ccc;
}
.todo:last-child{
border: 0
}
.todo p{
font-size: 24px;
font-weight: bold;
}
.buttons button{
background-color: transparent;
color: #aaa;
border: 0;
font-size: 24px;
cursor: pointer;
transition: all .5s ease-in-out;
}
.buttons button:hover{
color:black;
}
.todo.done p{
text-decoration: line-through;
text-decoration-thickness: 2px;
color: orangered;
text-decoration-style:double;
}
<div class="container">
<div class="add">
<label>ADD TODO</label>
<input type="text" placeholder="Write your To do">
</div>
<div class="todos">
<div class="todo">
<p>Todo 1</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 2</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 3</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
</div>
</div>

虽然委派是一个非常好的解决方案,但我倾向于采用(在我的opionion中(更简单的方法,并简单地将处理程序绑定到新元素:

const todoInp = document.querySelector('.add input')
const todos = document.querySelector('.todos')

const remove = document.querySelectorAll('.remove')
const doneBtns = document.querySelectorAll('.check')
todoInp.addEventListener('keyup', (e) => {
if (e.key === 'Enter' && e.target.value !== '') {
const todoVal = e.target.value
const todo = document.createElement('div')
todo.classList.add('todo')
todo.innerHTML = `
<p>${todoVal}</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
`
todos.appendChild(todo)
bindRemove(todo.querySelector('.remove'));
bindDone(todo.querySelector('.check'));
todoInp.value = ''
}
})
const bindDone = (btn) => {
btn.addEventListener('click', () => {
const mainPar = btn.parentElement.parentElement
mainPar.classList.toggle('done')
})
}
const bindRemove = (btn) => {
btn.addEventListener('click', () => {
const parent = btn.parentElement
const mainPar = parent.parentElement
mainPar.remove()
})
}
doneBtns.forEach(bindDone)
remove.forEach(bindRemove)
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0;
padding: 0;
margin-top: 50px;
height: 100vh;
background-color: aliceblue;
}
.container{
width: 600px;
height: auto;
padding: 50px;
}
.add,
.todos{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.add label{
font-family: 'Courier New', Courier, monospace;
font-weight: bold;
color: darkblue;
}
.add input{
background: white;
padding: 13px;
border: 0.5px solid #ccc;
width: 90%;
border-radius: 4px;
}
.add input:focus{
outline: none;
}
.add input::placeholder{
color:#ccc
}
.todo{
color: darkblue;
width: 90%;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ccc;
}
.todo:last-child{
border: 0
}
.todo p{
font-size: 24px;
font-weight: bold;
}
.buttons button{
background-color: transparent;
color: #aaa;
border: 0;
font-size: 24px;
cursor: pointer;
transition: all .5s ease-in-out;
}
.buttons button:hover{
color:black;
}
.todo.done p{
text-decoration: line-through;
text-decoration-thickness: 2px;
color: orangered;
text-decoration-style:double;
}
<div class="container">
<div class="add">
<label>ADD TODO</label>
<input type="text" placeholder="Write your To do">
</div>
<div class="todos">
<div class="todo">
<p>Todo 1</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 2</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 3</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
</div>
</div>

删除或添加todo后,您需要更新按钮列表。这很难做到,我建议你这样使用:您必须编辑HTML按钮,使其看起来像这样:

<button class="remove" onclick="remove(this)">x</button>
<button class="check" onclick="done(this)">y</button>

之后,将您的javascript文件更改为:

const todoInp = document.querySelector('.add input')
const todos = document.querySelector('.todos')

todoInp.addEventListener('keyup', (e) => {
if (e.key === 'Enter' && e.target.value !== '') {
const todoVal = e.target.value
const todo = document.createElement('div')
todo.classList.add('todo')
todo.innerHTML = `
<p>${todoVal}</p>
<div class="buttons">
<button class="remove" onclick="remove(this)">x</button>
<button class="check" onclick="done(this)">y</button>
</div>
`
todos.appendChild(todo)
todoInp.value = ''

}
})

function done(btn){
const mainPar = btn.parentElement.parentElement
mainPar.classList.toggle('done')
}
function remove(btn){
const parent = btn.parentElement
const mainPar = parent.parentElement
mainPar.remove()
}

X和Y按钮不工作的原因是querySelectorAll在新按钮存在之前已经运行,因此无法添加addEventListener。

使用事件委派,您只需要在父元素上单击一次事件。然后在事件处理程序中,您可以检查按下了哪个元素。

const todoInp = document.querySelector('.add input');
const todos = document.querySelector('.todos');
todoInp.addEventListener('keyup', (e) => {
if (e.key === 'Enter' && e.target.value !== '') {
const todoVal = e.target.value;
const todo = document.createElement('div');
todo.classList.add('todo');

todo.innerHTML = `
<p>${todoVal}</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
`;
todos.appendChild(todo);
todoInp.value = '';
}
})
// Add a single click event to the todos wrapper
todos.addEventListener('click', (e) => {
// exit if we don't click on a button
if(e.target.nodeName !== 'BUTTON') return;

// get `mainPar` element
const mainPar = e.target.parentElement.parentElement;

// remove todo item
if(e.target.classList.contains('remove')) {
return mainPar.remove();
}

// check todo item
if(e.target.classList.contains('check')) {
return mainPar.classList.toggle('done');
}
}, false);
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0;
padding: 0;
margin-top: 50px;
height: 100vh;
background-color: aliceblue;
}
.container{
width: 600px;
height: auto;
padding: 50px;
}
.add,
.todos{
display: flex;
flex-direction: column;
align-items: flex-start;
}
.add label{
font-family: 'Courier New', Courier, monospace;
font-weight: bold;
color: darkblue;
}
.add input{
background: white;
padding: 13px;
border: 0.5px solid #ccc;
width: 90%;
border-radius: 4px;
}
.add input:focus{
outline: none;
}
.add input::placeholder{
color:#ccc
}
.todo{
color: darkblue;
width: 90%;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ccc;
}
.todo:last-child{
border: 0
}
.todo p{
font-size: 24px;
font-weight: bold;
}
.buttons button{
background-color: transparent;
color: #aaa;
border: 0;
font-size: 24px;
cursor: pointer;
transition: all .5s ease-in-out;
}
.buttons button:hover{
color:black;
}
.todo.done p{
text-decoration: line-through;
text-decoration-thickness: 2px;
color: orangered;
text-decoration-style:double;
}
<div class="container">
<div class="add">
<label>ADD TODO</label>
<input type="text" placeholder="Write your To do">
</div>
<div class="todos">
<div class="todo">
<p>Todo 1</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 2</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
<div class="todo">
<p>Todo 3</p>
<div class="buttons">
<button class="remove">x</button>
<button class="check">y</button>
</div>
</div>
</div>
</div>

最新更新