是否可以在 javascript 中删除给定元素的所有事件处理程序?

Posted

技术标签:

【中文标题】是否可以在 javascript 中删除给定元素的所有事件处理程序?【英文标题】:Is it possible to remove all event handlers of a given element in javascript? 【发布时间】:2011-02-19 17:17:52 【问题描述】:

我想删除给定事件类型的所有处理程序。假设我已经向按钮添加了两次“onclick 事件”,现在我想返回到没有为按钮设置事件处理程序的原始状态。

我该怎么做?

PS:我找到了 removeEventListener(非 IE)/detachEvent(IE)方法,但函数希望我将处理事件的函数作为参数传递,这在我看来很笨拙,因为我必须存储在某处发挥作用。

编辑:http://ejohn.org/blog/flexible-javascript-events/ - 我现在正在使用此代码

【问题讨论】:

你使用的是内联 onclick 属性吗? 更好、更直接的选择是使用@jiggy 的解决方案***.com/questions/803936/… 【参考方案1】:

使用 jQuery 或类似的框架来管理所有事件处理程序可能是个好主意。 这将为您提供易于使用、不显眼的功能来添加和删除事件处理程序:

$(...).on('click', function()  ... );
$(...).off('click');
// or, to unbind all events:
$(...).off();

【讨论】:

我想了解它是如何工作的。它是否只是将函数存储在某个地方,并且 unbind() 只是遍历函数列表并调用 removeEventListener? 内部存储一个事件列表 $("*").unbind(); 将删除所有元素的所有事件处理程序,如果您尝试这样做的话。 对于今天查看此线程的任何人,unbind() 已被弃用很长时间。请改用.off() 自从 ykadaru 更新了这个,我还要指出 jQuery 不是原始问题的一部分,尽管在 2010 年它可能是最好的方法。现在,它不是。总的来说,随着现代浏览器现在广泛支持 ES6,jQuery 本身基本上已被整体弃用。 IMO,它的开销已经不值得了。【参考方案2】:

如果您的元素的父元素下只有一个子元素(或者如果您不介意所有兄弟的事件处理程序也丢失):

elem.parentElement.innerhtml = elem.parentElement.innerHTML;

在 Chrome 49、FF 44、IE 11 中测试

它会删除所有 'addEventListener'-s。

【讨论】:

我喜欢这个解决方案,因为它非常简单。如果它不是父节点下唯一的子元素,您始终可以将元素(例如,<button>)包装在 <span> 这在使用复杂框架的网站时也不起作用。元素死亡。【参考方案3】:

http://www.quirksmode.org/js/events_advanced.html - “注册了哪些事件处理程序?” - 似乎没有 DOM 3 级别是不可能的 :-(

编辑:我想出了这段代码。它适合我的需要。也许它对其他人会有所帮助。

Javascript:

function DomLib() 





/**
* Based on: http://ejohn.org/blog/flexible-javascript-events/
* Function that register event and enables it to be removed without explicitly giving the function definition
*/
DomLib.prototype.regEventEx = function (el, eventName, funct) 

  if (el.attachEvent) 
    el['e'+eventName+funct] = funct;
    el[eventName+funct] = function()el['e'+eventName+funct](window.event);
    el.attachEvent( 'on'+eventName, el[eventName+funct] );
   else     
    el.addEventListener(eventName, funct, false);
   

  if(!el.eventHolder) el.eventHolder = [];
  el.eventHolder[el.eventHolder.length] = new Array(eventName, funct);  


DomLib.prototype.removeEvent = function (obj, type, fn) 
  if (obj.detachEvent) 
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
   else 
    obj.removeEventListener( type, fn, false );
    



DomLib.prototype.hasEventEx = function (el, eventName, funct) 

  if (!el.eventHolder)   
    return false;
   else 
    for (var i = 0; i < el.eventHolder.length; i++) 
      if (el.eventHolder[i][0] == eventType && String(el.eventHolder[i][1]) == String(funct)) 
        return true;  
        
    
  
  return false;  


/** 
* @return - returns true if an event was removed
*/
DomLib.prototype.removeEventsByTypeEx = function (el, eventType) 

  if (el.eventHolder)   

    var removed = 0;
    for (var i = 0; i < el.eventHolder.length; i++) 
      if (el.eventHolder[i][0] == eventType)                 
        this.removeEvent(el, eventType, el.eventHolder[i][1]);
        el.eventHolder.splice(i, 1);
        removed++;
        i--;
        
    

    return (removed > 0) ? true : false;
   else 
    return false; 
  

测试 HTML 页面:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Expires" content="Fri, Jan 01 1900 00:00:00 GMT">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Lang" content="en">
<meta name="author" content="">
<meta http-equiv="Reply-to" content="@.com">
<meta name="generator" content="phpED 5.8">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="creation-date" content="01/01/2009">
<meta name="revisit-after" content="15 days">
<title>DomLibTest</title>
<link rel="stylesheet" type="text/css" href="my.css">
<!-- FILL IN: Location of your jQuery library -->
<script type="text/javascript" src="jQuery/jQuery-current.js"></script>
<!-- FILL IN: Plugin for debugging ... http://www.ecitadel.net/blog/2009/12/08/developing-jquery-use-dump-instead-alert -->
<script type="text/javascript" src="jQuery/jQuery.dump.js"></script>
<script type="text/javascript" src="DomLib.js"></script>
</head>
<body>

  <div id="testElem-1"></div>
  <script type="text/javascript">
  <!--

    var domLib = new DomLib();

    function removeTest(el) 

      var funct = function()  alert("#1: How Are You?");;
      var funct2 = function()  alert("#2: How Are You?");;                  

      domLib.regEventEx(el, "click", funct);
      domLib.regEventEx(el, "mousemove", funct2);
      domLib.regEventEx(el, "mousemove", funct2);
      domLib.regEventEx(el, "mousemove", funct2);

      $.dump(el.eventHolder);      
      domLib.removeEventsByTypeEx(el, "mousemove");      
      $.dump(el.eventHolder);
    

    removeTest(document.getElementById('testElem-1'));

  -->
  </script>
</body>
</html>

【讨论】:

【参考方案4】:

根据this thread,您可以使用 cloneNode 从 javascript 元素中剥离所有事件侦听器,如下所示:

 var new_element = old_element.cloneNode(true);
 old_element.parentNode.replaceChild(new_element, old_element);

【讨论】:

是的,但是下面的句子是:我相信即使元素被克隆,attachEvent 仍然存在,所以我不确定你会为 Internet Explorer 用户做什么。 这在使用复杂框架构建网站时不起作用。克隆后元素被破坏。【参考方案5】:

结合几种方法,包括从元素的属性列表中查找和删除所有“on...”事件属性,否则您只会删除 DOM 函数处理程序...

icompile.eladkarako.com/force-chrome-password-saving-by-removing-event-handlers-the-jsninja-way/

非常欢迎你添加你所有的 moo/jQuery/其他框架,因为以下任何一个都没有依赖关系(哎呀!如果甚至可以在 IE 中工作)

【讨论】:

【参考方案6】:
function removeEvents(elem) 
  var children = elem.children;
  for (var i = 0; i < children.length; i++) 
    var el = children[i];
    el.removeAttribute("onkeyup");
    el.removeAttribute("onmouseover");
    el.removeAttribute("onmouseout");
    el.removeAttribute("onclick");
    removeEvents(el);
  

这对我有用

【讨论】:

【参考方案7】:

据我所知,您根本无法向一个元素添加两个 onclick 处理程序。

假设 obj 是一个元素,那么 obj 的属性 onclick 被认为是一个函数,然后在该事件发生时作为方法调用。如果它不是一个函数,什么都不会发生。

JavaScript 继承自 Scheme 的一个非常有趣的属性,在 JavaScript 中,您不会像在 PHP 或 C 中那样定义函数。您创建匿名函数并将它们存储在变量中。 Javascript是'Lisp-1',没有函数标识符,有变量,可以容纳数字、数组和函数。

function name(arg) return arg;

如果我没有把真正的糖误认为是:

name = function(arg) return arg;;

'name' 这里是一个变量,无论我们如何定义该函数,我们也可以重新分配它。与 Java 的对象模型不同,在 Javascript 中,“方法”纯粹是一个属性,一个简单地保存可能使用或不使用“this”关键字的函数的变量。这就是为什么您不能同时拥有两个 onclick 事件的原因。运行时环境只需在您单击元素时调用名为“onclick”的元素的属性(预期包含一个函数)。将其视为与调用“main”启动程序相同的特殊类型行为。

要分配多个事件处理程序,请使用具有副作用的函数,例如。

obj.onclick = function firstEvent();secondEvent();

要更改或删除它,我们像任何变量一样重新分配或取消分配它。

obj.onclick = null;

如果我们需要以另一种方式调用该行为:

obj.onclick();

当然,我们也可以在该函数中使用 this 来更改对象本身或引用它。

编辑:哦等等,我现在明白你的意思是“一个按钮”有许多不同的按钮。

好吧,那么您只需收集所有元素,例如:

allElements = document.getElementsByTagName('*');

然后你使用循环:

var i = 0; while(obj = allElements[i++]) obj.onclick = null;

(不,那个单一的 = 不是错字)

【讨论】:

pastebin.org/237133 - 这是为一个按钮调用两个 onclick 处理程序的代码示例。 (在 Firefox 和 Chrome 中测试) -1 第一句中的错误信息。了解 JavaScript 中事件处理的工作原理并修复帖子以使其成为 +1

以上是关于是否可以在 javascript 中删除给定元素的所有事件处理程序?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript ES6,如果存在则从数组中删除项目的最佳方法,如果不存在则添加

是否可以删除“检查元素”?

几乎IncreasingSequence - Javascript

如何使用javascript删除css属性?

如何删除列表中列表中的第一个元素?

如何将 vh 中给定的元素的高度转换为像素?