函数在添加事件侦听器后运行了太多次

用户名

我已经创建了一个简单的演示(https://codepen.io/anon/pen/VgKQoq),其中包含单击按钮时要创建的元素和对象:它创建一个元素,然后将该元素的对象放入'objects '数组。单击删除按钮时,将使用ID成功删除元素和对象。

但是,问题在于,每次删除某个元素时,根据单击哪个元素,删除功能有时会运行太多次,我不知道为什么。在演示中,打开javascript控制台,创建例如4个元素,然后通过单击remove删除第三个元素,然后您会看到会发生什么。

有谁知道为什么会这样吗?我认为这可能是因为事件侦听器一次又一次地添加到了相同的元素,但是删除后似乎无法正常工作。谢谢您的任何解释和最佳做法。

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?
}
button { display: block }
.entry {
	width: 100%;
	display: block;
	padding: 10px;
	border: 1px solid #f5f5f5;
}
span {
  display: block;
  width: 100%;
}
section { background: lightgreen }
<button id='btn' onclick='createEntry()'>Create</button>
<section id='container'></section>

更新:还有其他想法吗?我已经添加了remove.removeEventListener("click", removeElements);它,现在它消除了很多重复,但是现在它仍然仅控制台日志两次(嗯...有时候!!)。上面更新了新的Codepen链接

T·斯托达德

我不确定到底发生了什么,但是您将所有这些函数嵌套在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))};
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

事件侦听器DOMNodeInserted被多次运行,为什么?

通过addEventListener添加的事件侦听器被多次调用

事件侦听器多次调用Javascript函数

在事件触发后添加事件侦听器“加载”

在事件侦听器中的匿名函数中运行函数

运行函数的函数 onclick 事件侦听器

添加事件侦听器后的原型继承问题

删除后重新添加事件侦听器--Javascript

获取单选按钮值后添加事件侦听器

为什么mousedown事件侦听器通过函数运行?

JavaScript函数/事件侦听器无法正常运行

OnChild事件侦听器被多次调用

jQuery事件侦听器多次触发

Liferay IPC侦听器运行多次

JTable上的侦听器问题(执行代码太多次)

如何在Jquery中多次调用函数以添加事件侦听器,而不仅仅是侦听最后一个?

事件侦听器中的匿名函数与事件侦听器中的匿名函数

如何使用on('change')将事件侦听器绑定到<script>运行后创建的元素?

不能多次调用FileReader事件侦听器

React keydown 事件侦听器被多次调用?

事件侦听器可多次用于Ajax驱动的html

等待异步函数后不调用 onload 事件侦听器

调用事件后等待事件侦听器完成

有什么方法可以访问在函数中添加了事件侦听器的元素?

如何向使用 ES6 模板文字创建的元素添加函数/事件侦听器?

如何使用 jQuery 在类构造函数上添加事件侦听器?

使用循环中调用的构造函数添加事件侦听器的问题

命名函数并向其添加事件侦听器会导致“未定义”

将参数传递给事件侦听器中的方法而不添加匿名函数