Javascript 向一个元素添加多个事件侦听器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11845678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
adding multiple event listeners to one element
提问by coiso
So my dilemma is that I don't want to write the same code twice. Once for the click event and another for the touchstart
event.
所以我的困境是我不想写两次相同的代码。一次用于单击事件,另一次用于touchstart
事件。
Here is the original code:
这是原始代码:
document.getElementById('first').addEventListener('touchstart', function(event) {
do_something();
});
document.getElementById('first').addEventListener('click', function(event) {
do_something();
});
How can I compact this? There HAS to be a simpler way!
我怎样才能压缩这个?必须有一个更简单的方法!
采纳答案by KooiInc
Maybe you can use a helper function like this:
也许你可以使用这样的辅助函数:
// events and args should be of type Array
function addMultipleListeners(element,events,handler,useCapture,args){
if (!(events instanceof Array)){
throw 'addMultipleListeners: '+
'please supply an array of eventstrings '+
'(like ["click","mouseover"])';
}
//create a wrapper to be able to use additional arguments
var handlerFn = function(e){
handler.apply(this, args && args instanceof Array ? args : []);
}
for (var i=0;i<events.length;i+=1){
element.addEventListener(events[i],handlerFn,useCapture);
}
}
function handler(e) {
// do things
};
// usage
addMultipleListeners(
document.getElementById('first'),
['touchstart','click'],
handler,
false);
回答by Allan Nienhuis
I know this is an old question, but I thought some might find this approach useful; it could be applied to any similarly repetitive code:
我知道这是一个老问题,但我认为有些人可能会发现这种方法很有用;它可以应用于任何类似的重复代码:
ES6
ES6
['click','ontouchstart'].forEach( evt =>
element.addEventListener(evt, dosomething, false)
);
ES5
ES5
['click','ontouchstart'].forEach( function(evt) {
element.addEventListener(evt, dosomething, false);
});
回答by Esailija
You can just define a function and pass it. Anonymous functions are not special in any way, all functions can be passed around as values.
您可以只定义一个函数并传递它。匿名函数并没有什么特别之处,所有函数都可以作为值传递。
var elem = document.getElementById('first');
elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);
function handler(event) {
do_something();
}
回答by Torsten Walter
For large numbers of events this might help:
对于大量事件,这可能会有所帮助:
var element = document.getElementById("myId");
var myEvents = "click touchstart touchend".split(" ");
var handler = function (e) {
do something
};
for (var i=0, len = myEvents.length; i < len; i++) {
element.addEventListener(myEvents[i], handler, false);
}
Update 06/2017:
06/2017 更新:
Now that new language features are more widely available you could simplify adding a limited list of events that share one listener.
现在,新的语言功能更广泛可用,您可以简化添加共享一个侦听器的有限事件列表。
const element = document.querySelector("#myId");
function handleEvent(e) {
// do something
}
// I prefer string.split because it makes editing the event list slightly easier
"click touchstart touchend touchmove".split(" ")
.map(name => element.addEventListener(name, handleEvent, false));
If you want to handle lots of events and have different requirements per listener you can also pass an objectwhich most people tend to forget.
如果您想处理大量事件并且对每个侦听器有不同的要求,您还可以传递一个大多数人往往会忘记的对象。
const el = document.querySelector("#myId");
const eventHandler = {
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handleClick(e);
break;
case "touchend":
this.handleTouchend(e);
break;
default:
this.handleDefault(e);
}
},
handleClick(e) {
// do something
},
handleTouchend(e) {
// do something different
},
handleDefault(e) {
console.log("unhandled event: %s", e.type);
}
}
el.addEventListener(eventHandler);
Update 05/2019:
05/2019 更新:
const el = document.querySelector("#myId");
const eventHandler = {
handlers: {
click(e) {
// do something
},
touchend(e) {
// do something different
},
default(e) {
console.log("unhandled event: %s", e.type);
}
},
// called for each event on this element
handleEvent(evt) {
switch (evt.type) {
case "click":
case "touchstart":
// click and touchstart share click handler
this.handlers.click(e);
break;
case "touchend":
this.handlers.touchend(e);
break;
default:
this.handlers.default(e);
}
}
}
Object.keys(eventHandler.handlers)
.map(eventName => el.addEventListener(eventName, eventHandler))
回答by Mattias Buelens
Unless your do_something
function actually does something with any given arguments, you can just pass it as the event handler.
除非您的do_something
函数实际上使用任何给定参数执行某些操作,否则您可以将其作为事件处理程序传递。
var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
回答by Armin
Simplest solution for me was passing the code into a separate function and then calling that function in an event listener, works like a charm.
对我来说最简单的解决方案是将代码传递到一个单独的函数中,然后在事件侦听器中调用该函数,就像一个魅力。
function somefunction() { ..code goes here ..}
variable.addEventListener('keyup', function() {
somefunction(); // calling function on keyup event
})
variable.addEventListener('keydown', function() {
somefunction(); //calling function on keydown event
})
回答by Strauss Bornman
I have a small solution that attaches to the prototype
我有一个附加到原型的小解决方案
EventTarget.prototype.addEventListeners = function(type, listener, options,extra) {
let arr = type;
if(typeof type == 'string'){
let sp = type.split(/[\s,;]+/);
arr = sp;
}
for(let a of arr){
this.addEventListener(a,listener,options,extra);
}
};
Allows you to give it a string or Array. The string can be separated with a space(' '), a comma(',') OR a Semicolon(';')
允许你给它一个字符串或数组。字符串可以用空格(' ')、逗号(',')或分号(';')分隔
回答by Ian Pollak
I just made this function (intentionally minified):
我刚刚做了这个功能(故意缩小):
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)
Usage:
用法:
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
// function body
});
The difference compared to other approaches is that the handling function is defined only once and then passed to every addEventListener
.
与其他方法相比的不同之处在于处理函数只定义一次,然后传递给 every addEventListener
。
EDIT:
编辑:
Adding a non-minified version to make it more comprehensible. The minified version was meant just to be copy-pasted and used.
添加非缩小版本以使其更易于理解。缩小版本只是为了复制粘贴和使用。
((element, event_names, handler) => {
event_names.forEach( (event_name) => {
element.addEventListener(event_name, handler)
})
})(element, ['click', 'touchstart'], (event) => {
// function body
});
回答by John Balvin Arias
document.getElementById('first').addEventListener('touchstart',myFunction);
document.getElementById('first').addEventListener('click',myFunction);
function myFunction(e){
e.preventDefault();e.stopPropagation()
do_something();
}
You should be using e.stopPropagation()
because if not, your function will fired twice on mobile
您应该使用,e.stopPropagation()
因为如果没有,您的功能将在移动设备上触发两次
回答by Luis Febro
This is my solution in which I deal with multiple events in my workflow.
这是我在工作流程中处理多个事件的解决方案。
let h2 = document.querySelector("h2");
function addMultipleEvents(eventsArray, targetElem, handler) {
eventsArray.map(function(event) {
targetElem.addEventListener(event, handler, false);
}
);
}
let counter = 0;
function countP() {
counter++;
h2.innerHTML = counter;
}
// magic starts over here...
addMultipleEvents(['click', 'mouseleave', 'mouseenter'], h2, countP);
<h1>MULTI EVENTS DEMO - If you click, move away or enter the mouse on the number, it counts...</h1>
<h2 style="text-align:center; font: bold 3em comic; cursor: pointer">0</h2>