我已经构建了一个简单的演示(https://codepen.io/anon/pen/VgKQoq),单击按钮时创建的元素和对象:它创建一个元素,然后将该元素的对象推入'对象'阵列.单击"删除"按钮时,将使用ID成功删除元素和对象.
但是,问题是每次删除一个元素时,remove函数有时会运行太多次,具体取决于单击的元素,我不知道为什么.在演示中,打开javascript控制台,创建例如4个元素,然后通过单击remove删除第3个元素,您将看到会发生什么.
有谁知道为什么会这样?我认为这可能是因为事件监听器一次又一次地添加到相同的元素,但它在删除时似乎不起作用.这里有任何解释和最佳实践,谢谢.
var id = 0, objects = [], removes;
function createEntry() {
id++;
// create new element, append to #container & create new object
var container = document.querySelector('#container'),
newEntry = document.createElement("div"),
title = 'title text here',
description = 'description text here',
remove = 'remove',
dataId = id,
obj = new Entry(title, description, remove);
newEntry.classList.add("entry");
newEntry.innerHTML = '<span class="title">' + title + '</span><span class="description">' + description + '</span><span class="remove">' + remove + '</span>';
container.appendChild(newEntry);
newEntry.setAttribute('data-id', id);
updateElements();
// constructor & push into array
function Entry(title, description, remove) {
this.title = title;
this.description = description;
this.remove = remove;
this.id = id;
objects.push(this);
}
// tests
console.log('JSON.stringify(obj): ' + JSON.stringify(obj));
console.log('obj.id: ' + obj.id);
function updateElements() {
removes = document.querySelectorAll(".remove");
listenForRemoves();
function listenForRemoves() {
for (let remove of removes) {
remove.removeEventListener("click", removeElements);
remove.addEventListener("click", removeElements);
}
}
function removeElements() {
let removedId = this.parentNode.getAttribute('data-id'),
objToRemove = objects.find(obj => obj.id == removedId); // not used
this.parentNode.remove(); console.log('removed id ' + removedId);
console.log('objects before: '); for (let object of objects) { console.log(JSON.stringify(object))};
objects = objects.filter(obj => obj.id != removedId); // doesn't use objToRemove
console.log('objects now: '); for (let object of objects) { console.log(JSON.stringify(object))};
}
}
// works but why the repeating console logs twice?
}Run Code Online (Sandbox Code Playgroud)
button { display: block }
.entry {
width: 100%;
display: block;
padding: 10px;
border: 1px solid #f5f5f5;
}
span {
display: block;
width: 100%;
}
section { background: lightgreen }Run Code Online (Sandbox Code Playgroud)
<button id='btn' onclick='createEntry()'>Create</button>
<section id='container'></section>Run Code Online (Sandbox Code Playgroud)
更新:还有其他想法吗?我添加了remove.removeEventListener("click", removeElements);哪些现在摆脱了很多重复,但它现在仍然只控制台日志两次(好吧......有时!?).上面更新了新的codepen链接
小智 1
我不确定到底发生了什么,但所有这些函数都嵌套在 createEntry 函数内。尝试将它们移到该函数之外。这似乎解决了我的测试中的问题:
var id = 0, objects = [], removes;
function createEntry() {
id++;
// create new element, append to #container & create new object
var container = document.querySelector('#container'),
newEntry = document.createElement("div"),
title = 'title text here',
description = 'description text here',
remove = 'remove',
dataId = id,
obj = new Entry(title, description, remove);
newEntry.classList.add("entry");
newEntry.innerHTML = '<span class="title">' + title + '</span><span class="description">' + description + '</span><span class="remove">' + remove + '</span>';
container.appendChild(newEntry);
newEntry.setAttribute('data-id', id);
updateElements();
// constructor & push into array
function Entry(title, description, remove) {
this.title = title;
this.description = description;
this.remove = remove;
this.id = id;
objects.push(this);
}
// tests
console.log('JSON.stringify(obj): ' + JSON.stringify(obj));
console.log('obj.id: ' + obj.id);
}
function updateElements() {
removes = document.querySelectorAll(".remove");
listenForRemoves();
function listenForRemoves() {
for (let remove of removes) {
remove.removeEventListener("click", removeElements);
remove.addEventListener("click", removeElements);
}
}
}
function removeElements(e) {
let removedId = this.parentNode.getAttribute('data-id'),
objToRemove = objects.find(obj => obj.id == removedId); // not used
this.parentNode.remove(); console.log('removed id ' + removedId);
console.log('objects before: '); for (let object of objects) { console.log(JSON.stringify(object) + " " + e.target)};
objects = objects.filter(obj => obj.id != removedId); // doesn't use objToRemove
console.log('objects now: '); for (let object of objects) { console.log(JSON.stringify(object))};
}
Run Code Online (Sandbox Code Playgroud)