У меня есть код, который, кажется, работает, но довольно странным образом. Когда я впервые обновляю страницу, у меня есть кнопка закрытия, которая, кажется, работает нормально, но когда я создаю новый элемент списка дел, кажется, что кнопка закрытия перестает работать, и я не могу точно определить, почему.
let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let close = document.querySelector(".close");
let toDo = document.querySelector(".todo");
/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo list */
addItem.addEventListener("click", addToDo);
function addToDo(){
var html = `
<ul class = "todo">
<li class = "toDoItem">
<p>${userInput.value}</p>
<div class = "close">X</div>
</li>
</ul>
`;
output.innerHTML += html;
// Resetting input to blank once a submit button has been added.
userInput.value = '';
}
// Figure out how to make closing functionality simple this implementation
// isn't working
close.addEventListener("click", function(e){
console.info("clicked");
let x = e.target.parentElement;
x.style.display = "none";
e.preventDefault();
});<header>
<input type = "text" placeholder = "Enter Item Here..." id = "toDoInput">
<button id = "submitButton">+</button>
</header>
<section id = "output">
<ul class = "todo">
<li class = "toDoItem">
<p>Clean Room!</p>
<div class = "close">X</div>
</li>
</ul>
</section>
<script src = "todo.js"></script>Я также не уверен, что использую передовой опыт, поскольку я новичок в веб-разработке, поэтому любые советы также будут внимательно оценены!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема здесь в том, что при повторном рендеринге содержимого раздела «output» вы теряете прослушиватель событий, привязанный к исходному элементу «.close». Несколько вариантов решения проблемы, посмотрите эта ветка для некоторых примеров.
Точно, он не может слушать то, чего не было.
Вам нужен обработчик событий в реальном времени на кнопках закрытия. Этот пример должен помочь. Чтобы предложить что-то большее, проще и проще использовать для этого jQuery, если вы можете и не возражаете использовать библиотеку JS.
Пример jQuery:
$(document).on("click", ".close", function() {
$(this).parent().hide();
});
Нет необходимости предотвращать поведение по умолчанию, так как это div.
Этот ответ находится в JQuery, поэтому не забудьте разместить его ВНЕ document.ready.
У вас есть довольно близкий человек, и вам точно не нужен jQuery.
Как вы можете видеть ниже, вам не нужно динамически подталкивать <ul>. Это никогда не изменится!
<header>
<input type = "text" placeholder = "Enter Item Here..." id = "toDoInput">
<button id = "submitButton">+</button>
</header>
<section id = "output">
<ul class = "todo">
</ul>
</section>
А вот и ваш отредактированный javascript:
let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let toDo = document.querySelector(".todo");
/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo
list */
addItem.addEventListener("click", addToDo);
function addToDo(e){
e.preventDefault();
var html = `<li class = "toDoItem">
<p>${userInput.value} </p> <p class = "close"
onclick = "removeChildElement(this);">X</p>
</li>`;
output.innerHTML += html;
let close = document.querySelector(".close")
// Resetting input to blank once a submit button has been added.
userInput.value = '';
}
// Figure out how to make closing functionality simple this implementation
// isn't working
function removeChildElement(e) {
let x = e.parentElement;
let xParent = x.parentElement;
xParent.removeChild(x);
console.info(xParent);
}
Как видите, я внес несколько изменений. Самое главное, проблема с кнопкой закрытия. Функция получает родителя от своего родителя (^ 2), а затем удаляет его потомка. Какой был бы ваш элемент <li>!
Наслаждайтесь скрипкой: https://jsfiddle.net/fjbyy6uw/35/
Используйте Делегирование событий. Подробности комментируются в Демо. Добавлен <form>, поэтому можно использовать HTMLFormControlsCollection API, это проще, меньше писать, и я ленив.
/* All form controls are referenced by HTMLFormControlsCollection */
var form = document.forms.toDo;
var td = form.elements;
var add = td.add;
var inp = td.input;
var out = td.output;
var toDo = document.querySelector('.toDo');
add.addEventListener("click", addToDo);
/* Limited the dynamically created node to `<li>`. It doesn't make sense to
|| have several `<ul>` having only one `<li>` each.
*/
function addToDo() {
var html = `
<li class = "item">
<span>${inp.value}</span>
<b class = "close">X</b>
</li>
`;
toDo.innerHTML += html;
}
/* Event Delegation is a way of leveraging event bubbling so
|| that a single ancestor node can be registered to listen for
|| an event (e.currentTarget) and by means event propagation
|| (bubbling) can locate the event origin (node clicked/e.target).
|| In this demo e.currentTarget is output#output and e.target are
|| any b.close. This was possibble by using e.target in conditions
*/
/* removeChild() is used because display:none is not entirely
|| gone. The markup remains just not in the DOM, so it may not
|| look like it's there, under certain conditions a node could be
|| considered present.
*/
out.addEventListener("click", function(e) {
if (e.target !== e.currentTarget) {
if (e.target.className === "close") {
let x = e.target.parentElement
x.parentElement.removeChild(x);
}
}
});.item {
display: flex;
max-width: 250px;
justify-content: space-between;
}
.item span,
.item b {
display: table-cell;
}
.item b {
cursor: pointer
}
input,
output,
button {
font: inherit
}<form id='toDo'>
<header>
<input type = "text" placeholder = "Enter Item Here..." id = "input">
<button id = "add" type='button'>+</button>
</header>
<output id = "output">
<ul class = "toDo">
<li class = "item">
<span>Clean Room!</span>
<b class = "close">X</b>
</li>
</ul>
</output>
</form>
Вы создаете элементы
.closeдинамически, поэтому вам необходимо использоватьevent delegation.