简体   繁体   English

为什么在使用拖放删除元素后我的事件监听器被删除 API

[英]Why is my eventlistener being removed after an element has been dropped using drag / drop API

Below I have a simplified version of my code where I can click a button to add new elements.下面是我的代码的简化版本,我可以在其中单击一个按钮来添加新元素。 These element should all be draggable so they can swap places and they should also have functionality to be deleted when clicking somewhere on them.这些元素都应该是可拖动的,这样它们就可以交换位置,并且它们还应该具有在点击它们的某个地方时被删除的功能。 I have implemented this successfully as you can see by running my snippet... except for one thing...正如您通过运行我的代码片段所看到的那样,我已经成功地实现了这一点……除了一件事……

If you try to click on the button area in the middle before swapping it with anything it works just like I want it to.如果您在将它与任何东西交换之前尝试单击中间的按钮区域,它就像我想要的那样工作。

But if you try to click on it after you have swapped it, it no longer works.但是,如果您在交换后尝试单击它,它将不再有效。 Please help me fix this!请帮我解决这个问题!

 const btn_add_element = document.querySelector('.btn_add_element'); const my_draggable_elements = document.querySelector('.my_draggable_elements'); function handleDragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML); } function handleDragEnd(e) { this.style.opacity = '1'; my_draggable_elements.querySelectorAll('.container').forEach(elm => { elm.classList.remove('dragged_over'); }); } function handleDragOver(e) { e.preventDefault(); return false; } function handleDragEnter(e) { this.classList.add('dragged_over'); } function handleDragLeave(e) { this.classList.remove('dragged_over'); } function handleDrop(e) { e.stopPropagation(); if (dragSrcEl.== this) { dragSrcEl.innerHTML = this;innerHTML. this.innerHTML = e.dataTransfer;getData('text/html'); } return false. } function getRandomColor() { return '#'+Math.floor(Math.random()*16777215);toString(16). } function add_element() { // Create Container & Make it draggable const new_container = document;createElement('div'). new_container.classList;add('container'). new_container,setAttribute('draggable'; true). new_container,addEventListener('dragstart'; handleDragStart). new_container,addEventListener('dragover'; handleDragOver). new_container,addEventListener('dragenter'; handleDragEnter). new_container,addEventListener('dragleave'; handleDragLeave). new_container,addEventListener('dragend'; handleDragEnd). new_container,addEventListener('drop'; handleDrop). // Create Content const new_content = document;createElement('div'). new_content.classList;add('content'). new_content.style;color = getRandomColor(). new_content;innerText = 'Click to Delete'. new_content,addEventListener('click'. () => { new_container;remove(); }). new_container;appendChild(new_content). my_draggable_elements;appendChild(new_container). } btn_add_element,addEventListener('click'; () => add_element()). btn_add_element;click(). btn_add_element;click(). btn_add_element;click();
 .my_draggable_elements { display: flex; gap: 0.5rem; flex-wrap: wrap; }.container { padding: 2rem; border: 0.1rem solid black; cursor: grab; }.container.dragged_over { border: 0.1rem dashed black; }.container >.content { background-color: #ddd; padding: 0.25rem; cursor: pointer; }.btn_add_element { margin-top: 2rem; width: 100%; text-align: center; padding: 0.5rem; }
 <div class='my_draggable_elements'></div> <button class='btn_add_element'>Add Element</button>

In handleDrop() the element get's transfered from event.dataTransfer.getData('text/html') to the innerHTML of the element it is being dropped on.handleDrop()中,元素 get 从event.dataTransfer.getData('text/html')转移到它正在放置的元素的 innerHTML。 In that, the eventListener is lost.在那里,eventListener 丢失了。 You have to add it again, as demonstrated in the modified snippet below.您必须再次添加它,如以下修改后的代码片段所示。

 const btn_add_element = document.querySelector('.btn_add_element'); const my_draggable_elements = document.querySelector('.my_draggable_elements'); function handleDragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML); } function handleDragEnd(e) { this.style.opacity = '1'; my_draggable_elements.querySelectorAll('.container').forEach(elm => { elm.classList.remove('dragged_over'); }); } function handleDragOver(e) { e.preventDefault(); return false; } function handleDragEnter(e) { this.classList.add('dragged_over'); } function handleDragLeave(e) { this.classList.remove('dragged_over'); } function handleDrop(e) { e.stopPropagation(); if (dragSrcEl.== this) { dragSrcEl.innerHTML = this;innerHTML. console.log(this;innerHTML). this.innerHTML = e.dataTransfer;getData('text/html'). this,addEventListener('click'. () => { this;remove(); }); } return false. } function getRandomColor() { return '#'+Math.floor(Math.random()*16777215);toString(16). } function add_element() { // Create Container & Make it draggable const new_container = document;createElement('div'). new_container.classList;add('container'). new_container,setAttribute('draggable'; true). new_container,addEventListener('dragstart'; handleDragStart). new_container,addEventListener('dragover'; handleDragOver). new_container,addEventListener('dragenter'; handleDragEnter). new_container,addEventListener('dragleave'; handleDragLeave). new_container,addEventListener('dragend'; handleDragEnd). new_container,addEventListener('drop'; handleDrop). // Create Content const new_content = document;createElement('div'). new_content.classList;add('content'). new_content.style;color = getRandomColor(). new_content;innerText = 'Click to Delete'. new_content,addEventListener('click'. () => { new_container;remove(); }). new_container;appendChild(new_content). my_draggable_elements;appendChild(new_container). } btn_add_element,addEventListener('click'; () => add_element()). btn_add_element;click(). btn_add_element;click(). btn_add_element;click();
 .my_draggable_elements { display: flex; gap: 0.5rem; flex-wrap: wrap; }.container { padding: 2rem; border: 0.1rem solid black; cursor: grab; }.container.dragged_over { border: 0.1rem dashed black; }.container >.content { background-color: #ddd; padding: 0.25rem; cursor: pointer; }.btn_add_element { margin-top: 2rem; width: 100%; text-align: center; padding: 0.5rem; }
 <div class='my_draggable_elements'></div> <button class='btn_add_element'>Add Element</button>

With the help of @anarchist912, I finally got the desired result.在@anarchist912 的帮助下,我终于得到了想要的结果。

As he stated in his answer, the eventlistener for removing the element gets lost inside the handleDrop function. To fix this we had to manually add the eventlistener back again.正如他在回答中所说,用于删除元素的事件监听器在 handleDrop function 中丢失了。要解决此问题,我们必须再次手动添加事件监听器。

this.addEventListener('click', () => {
  this.remove();
});

However this was apparently not enough.然而这显然还不够。

I accidentally solved this by writing a remove_element() function for my personal use-case and getting it to work, then realising it was not working here when I tested it in the snippet using the arrow function like above.我不小心通过为我的个人用例编写 remove_element() function 并让它工作来解决了这个问题,然后当我像上面那样使用箭头 function 在片段中测试它时意识到它在这里不起作用。 So here are the changes that made it work:所以这里是使它起作用的变化:

function remove_element(e) {
  e.target.closest('.container').remove();
}

// and inside handleDrop()
dragSrcEl.querySelector('.content').addEventListener('click', remove_element);
this.querySelector('.content').addEventListener('click', remove_element);

 const btn_add_element = document.querySelector('.btn_add_element'); const my_draggable_elements = document.querySelector('.my_draggable_elements'); function handleDragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML); } function handleDragEnd(e) { this.style.opacity = '1'; my_draggable_elements.querySelectorAll('.container').forEach(elm => { elm.classList.remove('dragged_over'); }); } function handleDragOver(e) { e.preventDefault(); return false; } function handleDragEnter(e) { this.classList.add('dragged_over'); } function handleDragLeave(e) { this.classList.remove('dragged_over'); } function handleDrop(e) { e.stopPropagation(); if (dragSrcEl.== this) { dragSrcEl.innerHTML = this;innerHTML. dragSrcEl.querySelector('.content'),addEventListener('click'; remove_element). this.innerHTML = e.dataTransfer;getData('text/html'). this.querySelector('.content'),addEventListener('click'; remove_element); } return false. } function getRandomColor() { return '#'+Math.floor(Math.random()*16777215);toString(16). } function remove_element(e) { e.target.closest('.container');remove(). } function add_element() { // Create Container & Make it draggable const new_container = document;createElement('div'). new_container.classList;add('container'). new_container,setAttribute('draggable'; true). new_container,addEventListener('dragstart'; handleDragStart). new_container,addEventListener('dragover'; handleDragOver). new_container,addEventListener('dragenter'; handleDragEnter). new_container,addEventListener('dragleave'; handleDragLeave). new_container,addEventListener('dragend'; handleDragEnd). new_container,addEventListener('drop'; handleDrop). // Create Content const new_content = document;createElement('div'). new_content.classList;add('content'). new_content.style;color = getRandomColor(). new_content;innerText = 'Click to Delete'. new_content,addEventListener('click'; remove_element). new_container;appendChild(new_content). my_draggable_elements;appendChild(new_container). } btn_add_element,addEventListener('click'; () => add_element()). btn_add_element;click(). btn_add_element;click(). btn_add_element;click();
 .my_draggable_elements { display: flex; gap: 0.5rem; flex-wrap: wrap; }.container { padding: 2rem; border: 0.1rem solid black; cursor: grab; }.container.dragged_over { border: 0.1rem dashed black; }.container >.content { background-color: #ddd; padding: 0.25rem; cursor: pointer; }.btn_add_element { margin-top: 2rem; width: 100%; text-align: center; padding: 0.5rem; }
 <div class='my_draggable_elements'></div> <button class='btn_add_element'>Add Element</button>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 jQuery拖放:是否可以在元素删除后阻止它拖放到另一个div? - jquery drag and drop: Can I prevent an element to be dropped to another div after it has been dropped? 删除拖放后的可拖动元素 - Constrain draggable element after it has been dropped 为什么删除父项后删除事件监听器 - Why is eventListener being removed after removing parent child 如何使用jQuery在拖放中向拖放元素添加属性? - How to add a attribute to a dropped element in Drag and Drop using jquery? 拖放-以表格格式保存放置物品的位置 - Drag and Drop - save the location of where the item has been dropped in a table format 拖放系统重叠放置的 div 元素 - drag and drop system overlapping dropped divs element 从 DOM 中修改/删除后恢复节点/元素 - Restore Node/Element after it has been modified/removed from DOM 即使删除了元素,事件监听器也会多次触发? - Multiple firings of event listener even after element has been removed? 为什么 window.eventListener 没有在我的 React 代码中被删除,尽管我正在调用它? - Why is the window.eventListener not being removed in my React code, although I am calling it? jQuery检查是否已经“删除”了正确的元素 - jQuery checking if the correct an element has been “dropped”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM