0

我开发了一个主要使用标准的'allowdrop','drag'和'drop'事件的javascript拖放。在离开页面之前删除事件监听器

我想自定义'幻影'拖动的对象,所以我添加了一个display:none div,它使用可拖动元素的innerHTML填充,并在用户开始拖动时变为可见(display:block;)。

可拖动的div绝对定位并匹配鼠标移动。为此我需要将3个事件监听器添加到document.body。他们如下:

document.body.addEventListener('dragover', function (ev) { 
    console.log("dragover event triggered"); 
    ev = ev || window.event; 
    ev.preventDefault(); 
    dragX = ev.pageX; 
    dragY = ev.pageY; 
    document.getElementById("dragged-container").style.left = (dragX - dragOffsetX) + "px"; 
    document.getElementById("dragged-container").style.top = (dragY - dragOffsetY - 10) + "px";  
    if (mostRecentHoveredDropTargetId!="") { 
     if (dragX<mostRecentHoveredDropTargetRect.left || dragX>mostRecentHoveredDropTargetRect.right || dragY<mostRecentHoveredDropTargetRect.top || dragY>mostRecentHoveredDropTargetRect.bottom) { 
      document.getElementById(mostRecentHoveredDropTargetId).classList.remove("drop-target-hover"); 
      mostRecentHoveredDropTargetId = ""; 
     } 
    } 
}); 

document.body.addEventListener('drop', function (ev) { 
    console.log("drop event triggered"); 
    ev.preventDefault(); 
    var data = ev.dataTransfer.getData("text"); // data set to the id of the draggable element 
    if (document.getElementById(data)!=null) { 
     document.getElementById(data).classList.remove("dragged"); 
     document.getElementById("dragged-container").innerHTML = ""; 
     document.getElementById("dragged-container").style.display = "none"; 
     var draggablesClasses = document.getElementById(data).className; 
     if ((draggablesClasses.indexOf('draggable')==-1 || draggablesClasses=="") && document.getElementById(data).getAttribute('draggable')=="true") { 
      if (draggablesClasses=="") { 
       document.getElementById(data).className += "draggable"; 
      } else { 
       document.getElementById(data).className += " draggable"; 
      } 
     } 
    } 
}); 

// resets dragged-container and origin .draggable, when mouse released outside browser window 
document.body.addEventListener('mouseleave', function (ev) { 
    if (jqueryReady==true) { 
     $(".dragged").addClass("draggable"); 
     $(".dragged").removeClass("dragged"); 
    } 
    document.getElementById("dragged-container").innerHTML = ""; 
    document.getElementById("dragged-container").style.display = "none"; 
}); 

这一切工作正常。拖放完全按照我的预期执行。

问题是,当我去另一个页面,显然那些身体事件侦听器仍在运行。

我在这里看到了很多答案,并尝试了我见过的所有内容。对于初学者来说这一点:

window.onunload = function() { 
    console.log("about to clear event listeners prior to leaving page"); 
    document.body.removeEventListener('dragover', null); 
    document.body.removeEventListener('drop', null); 
    document.body.removeEventListener('mouseleave', null); 
    return; 
} 

...但输出的console.log也不出现(更不用说“空的是错的,我敢肯定)。我也试过这个,在jQuery ready函数中:

$(window).bind('beforeunload', function(){ 
     console.log("about to clear event listeners prior to leaving page"); 
     document.body.removeEventListener('dragover', null); 
     document.body.removeEventListener('drop', null); 
     document.body.removeEventListener('mouseleave', null); 
    }); 

..但是,控制台再一次没有收到那个输出。

我也尝试了上面的'onbeforeunload'和'onunload'。

我在做什么错? - 特别是与删除这些window.body事件监听器,我的意思是(任何其他我可以稍后解决)。

谢谢。

回答

0

removeEventListener需要处理

不要使用匿名函数是解决方案。 像这样:

var dragHandler = function (ev) { 
    console.log("dragover event triggered"); 
}; 
document.body.addEventListener('dragover', dragHandler); 

后:

window.onunload = function() { 
    console.log("about to clear event listeners prior to leaving page"); 
    document.body.removeEventListener('dragover', dragHandler); 
    return; 
} 
+0

感谢您的快速回复。我知道'null'可能是错误的,但那不是我的直接问题。我更新了我的代码,拖放仍然有效,但是和.onunload函数一样,甚至没有调用 - 没有控制台输出。我想到,我可以将添加和删除事件行放在拖动元素的“拖动”和“拖放”事件处理程序中。这似乎已经成功了。但感谢您清除非匿名函数问题。 – moosefetcher