确保不会多次添加相同的事件侦听器
Posted
技术标签:
【中文标题】确保不会多次添加相同的事件侦听器【英文标题】:make sure the same event listener is not added more than once 【发布时间】:2016-03-24 09:02:59 【问题描述】:我正在实现一个单例IEventDispatcher
类,但遇到了一个问题,有时我将相同的事件侦听器函数多次添加到我的实例中。我尝试按如下方式保留eventFunctions
的数组,以不多次添加事件,但它似乎没有按预期工作。
private var eventFunctions:Array =[];
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
if(dispatcher.hasEventListener(type) && eventFunctions.indexOf(listener) > -1)
trace("adding event listener that already exists " + type + " with function " + listener);
return;
dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
【问题讨论】:
您似乎从未填充数组?除其他事项外。还有比你展示的更多吗?如果你有多个事件回调同一个函数怎么办?这种方法也否定了弱引用的好处。 我建议仅在 useweakreference = false 时跟踪事件/侦听器。这是相当重要的。我个人使用 Object 来跟踪事件类型(因为它们都是字符串),然后在我的 Object 键中存储 Vector.首先请注意,多次添加监听器没有问题 - 只要对象/调度程序、回调函数和 useCapture 参数相同,它实际上不会添加另一个监听器。
例如:
bob.addEventListener(MouseEvent.CLICK, clickHandler);
bob.addEventListener(MouseEvent.CLICK, clickHandler, false);
function clickHandler(e:Event):void trace("clicky"); ;
每次点击只会产生 1 个跟踪。
现在,如果您将其更改为:
bob.addEventListener(MouseEvent.CLICK, clickHandler, false);
bob.addEventListener(MouseEvent.CLICK, clickHandler, true); //<-- use capture is true on this one
现在您将获得每次点击的两条轨迹。
现在,如果除了第一点之外,您还需要在单例中跟踪所有听众,我建议您这样做:
//instead of an array, use a dictionary so you can have weak keys that don't prevent your objects from being garbage collected
private static var listeners:Dictionary = new Dictionary(true);
//you need to pass the dispatcher into the function (missing from your question code)
public function addEventListener(dispatcher:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
//check is there a record in the dictionary for this object (array)
if(listeners[dispatcher])
//loop through the array and see if there are any matches
for(var i:int=0;i<listeners[dispatcher].length;i++)
if(listeners[dispatcher][i] && listeners[dispatcher][i].listener == listener
&& listeners[dispatcher][i].type == type
&& listeners[dispatcher][i].useCapture == useCapture
&& listeners[dispatcher][i].useWeakReference == useWeakReference)
trace("adding event listener that already exists " + type + " with function " + listener);
return;
//add the listener to the dispatcher
dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
//if no record exists yet, create the array and associate it with this dispatcher
if(!listeners[dispatcher]) listeners[dispatcher] = new Array();
//add the parameters just used to the array.
listeners[dispatcher].push(listener: listener, useCapture: useCapture, useWeakReference: useWeakReference);
//you will need a way to remove the listeners as well
public function removeEventListener(dispatcher:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false):void
if(listeners[dispatcher] && listeners[dispatcher].length > 0)
//loop through the array and see if there any matches
for(var i:int=0;i<listeners[dispatcher].length;i++)
if(listeners[dispatcher][i] && listeners[dispatcher][i].listener == listener
&& listeners[dispatcher][i].type == type
&& listeners[dispatcher][i].useCapture == useCapture)
//remove the event form the dispatcher
dispatcher.removeEventListener(type, listener, useCapture);
//remove the item from the array
listeners[dispatcher].splice(i,1);
//if the array is now empty, remove the dictionary item
if(listeners[dispatcher].length < 1) delete listeners[dispatcher];
//exit the function now
return;
【讨论】:
这都是我脑子里写的,所以未经测试,可能有错别字。 如果您使用 useweakreference = true 跟踪事件集,您将破坏 useweakreference 系统。最好不要触摸使用 useweakreference = true 设置的事件(意味着根本不跟踪它们) 接受这一点,因为它回答了发布的问题。我不理解我的问题以及我应该理解的问题,它与我发布的内容并不完全相关,但我现在已经解决了。以上是关于确保不会多次添加相同的事件侦听器的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Jquery 中多次调用一个函数来添加一个事件监听器而不只是监听最后一个?