是否可以在 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,如果存在则从数组中删除项目的最佳方法,如果不存在则添加