将多个事件侦听器添加到一个元素
adding multiple event listeners to one element
所以我的困境是我不想写两次相同的代码。一次用于点击事件,另一次用于touchstart
事件。
这是原始代码:
document.getElementById('first').addEventListener('touchstart', function(event) {
do_something();
});
document.getElementById('first').addEventListener('click', function(event) {
do_something();
});
我怎样才能压缩它?必须有一个更简单的方法!
我认为有些人可能会发现这种方法很有用;它可以应用于任何类似的重复代码:
ES6
['click','ontouchstart'].forEach( evt =>
element.addEventListener(evt, dosomething, false)
);
ES5
['click','ontouchstart'].forEach( function(evt) {
element.addEventListener(evt, dosomething, false);
});
你可以定义一个函数并传递它。匿名函数在任何方面都不特殊,所有函数都可以作为值传递。
var elem = document.getElementById('first');
elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);
function handler(event) {
do_something();
}
也许你可以使用这样的帮助程序函数:
// 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);
[编辑2020年11月] 这个答案很古老。我现在解决这个问题的方法是使用一个actions
对象,其中每个事件类型指定处理程序,一个元素的data-attribute
指示应该对其执行哪个操作和一个通用的文档范围的处理程序方法(所以事件委托)。
const firstElemHandler = (elem, evt) =>
elem.textContent = `You ${evt.type === "click" ? "clicked" : "touched"}!`;
const actions = {
click: {
firstElemHandler,
},
touchstart: {
firstElemHandler,
},
mouseover: {
firstElemHandler: elem => elem.textContent = "Now ... click me!",
outerHandling: elem => {
console.clear();
console.log(`Hi from outerHandling, handle time ${
new Date().toLocaleTimeString()}`);
},
}
};
Object.keys(actions).forEach(key => document.addEventListener(key, handle));
function handle(evt) {
const origin = evt.target.closest("[data-action]");
return origin &&
actions[evt.type] &&
actions[evt.type][origin.dataset.action] &&
actions[evt.type][origin.dataset.action](origin, evt) ||
true;
}
[data-action]:hover {
cursor: pointer;
}
<div data-action="outerHandling">
<div id="first" data-action="firstElemHandler">
<b>Hover, click or tap</b>
</div>
this is handled too (on mouse over)
</div>
对于大量事件,这可能会有所帮助:
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);
}
更新 06/2017:
现在,新的语言功能可以更广泛地使用,您可以简化添加共享一个侦听器的有限事件列表的过程。
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));
如果你想处理很多事件,并且每个侦听器有不同的要求,你也可以传递一个大多数人容易忘记的对象。
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);
更新 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))
除非你的do_something
函数实际上对任何给定的参数做了一些事情,否则你可以把它作为事件处理程序传递。
var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
最简单的解决方案是将代码传递到一个单独的函数中,然后在事件侦听器中调用该函数,就像一个魅力。
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
})
JavaScript编码的新手,所以如果我错了,请原谅我。我认为您可以创建一个对象和事件处理程序,如下所示:
const myEvents = {
click: clickOnce,
dblclick: clickTwice,
};
function clickOnce() {
console.log("Once");
}
function clickTwice() {
console.log("Twice");
}
Object.keys(myEvents).forEach((key) => {
const myButton = document.querySelector(".myButton")
myButton.addEventListener(key, myEvents[key]);
});
<h1 class="myButton">Button</h1>
然后click
元素。
我有一个附加到原型的小解决方案
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);
}
};
允许您为其提供字符串或数组。字符串可以用空格 (' ')、逗号 (',') 或分号(';')分隔
我刚刚做了这个函数(故意缩小):
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)
用法:
((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
// function body
});
与其他方法相比的不同之处在于,处理函数仅定义一次,然后传递给每个addEventListener
。
编辑:
添加非缩小版本以使其更易于理解。缩小后的版本只是为了复制粘贴和使用。
((element, event_names, handler) => {
event_names.forEach( (event_name) => {
element.addEventListener(event_name, handler)
})
})(element, ['click', 'touchstart'], (event) => {
// function body
});
像这样的事情呢:
['focusout','keydown'].forEach( function(evt) {
self.slave.addEventListener(evt, function(event) {
// Here `this` is for the slave, i.e. `self.slave`
if ((event.type === 'keydown' && event.which === 27) || event.type === 'focusout') {
this.style.display = 'none';
this.parentNode.querySelector('.master').style.display = '';
this.parentNode.querySelector('.master').value = this.value;
console.log('out');
}
}, false);
});
// The above is replacement of:
/* self.slave.addEventListener("focusout", function(event) { })
self.slave.addEventListener("keydown", function(event) {
if (event.which === 27) { // Esc
}
})
*/
document.getElementById('first').addEventListener('touchstart',myFunction);
document.getElementById('first').addEventListener('click',myFunction);
function myFunction(e){
e.preventDefault();e.stopPropagation()
do_something();
}
您应该使用e.stopPropagation()
因为如果没有,您的函数将在移动设备上触发两次
这是我的解决方案,我在其中处理工作流程中的多个事件。
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>
简单地迭代Object
。这可以处理单个或多个元素。这是一个示例:
const ELEMENTS = {'click': element1, ...};
for (const [key, value] of Object.entries(ELEMENTS)) {
value.addEventListener(key, () => {
do_something();
});
}
添加事件时,key
是事件类型,value
是元素,因此您可以编辑ELEMENTS
添加元素和事件类型。
相关,但这用于初始化特定于每个元素的唯一事件侦听器。
您可以使用滑块实时显示值,或检查控制台。在<input>
元素上,我有一个名为 data-whatever
的attr
标签,因此您可以根据需要自定义该数据。
sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
item.addEventListener('input', (e) => {
console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
item.nextElementSibling.textContent = e.target.value;
});
})
.wrapper {
display: flex;
}
span {
padding-right: 30px;
margin-left: 5px;
}
* {
font-size: 12px
}
<div class="wrapper">
<input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
<em>50</em>
<span>Size</span>
<br>
<input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
<em>50</em>
<span>OriginY</span>
<br>
<input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
<em>50</em>
<span>OriginX</span>
</div>
//catch volume update
var volEvents = "change,input";
var volEventsArr = volEvents.split(",");
for(var i = 0;i<volknob.length;i++) {
for(var k=0;k<volEventsArr.length;k++) {
volknob[i].addEventListener(volEventsArr[k], function() {
var cfa = document.getElementsByClassName('watch_televised');
for (var j = 0; j<cfa.length; j++) {
cfa[j].volume = this.value / 100;
}
});
}
}
html中的"onclick"适用于触摸和点击事件。下面是示例。
对于那些正在寻找jQuery解决方案的人来说,可以这样做:
$('#selector').on('click touchstart', function() {
//do something here
});
或:
$('#selector').on('click touchstart', myFunction);
这个迷你JavaScript库(1.3 KB)可以做所有这些事情
https://github.com/Norair1997/norjs/
nor.event(["#first"], ["touchstart", "click"], [doSomething, doSomething]);
- 使用clickToggle并在单击另一个元素时关闭元素
- 表追加而不附加最后一个元素
- 滚动到容器中的下一个元素-几乎到了
- 使用CSS或js,使用动态选择器选择任意li的下一个元素
- 按我自己的类克隆另一个元素的内容和顺序
- Javascript获取上一个元素的内容
- 如何通过HTML+CSS中的另一个元素Selector更改元素的属性值
- 在数组中的一个元素上设置多个值
- 无法选择除一个元素外的所有元素
- 使用jquery contains获取一个元素并添加类
- $(.class).empty总是缺少一个元素
- jQuery-将列表项的一个元素移动到同一项的另一个元素中+对我的列表中的每个项执行此操作
- 如何在一个元素动画之后延迟
- jQuery转盘下一个元素没有滑入
- jquery从另一个元素中移除移除
- DIV怎么能像Javascript中的另一个元素一样工作呢
- 当知道同一hiearch中至少有一个元素时,遍历到元素.结构使用jquery
- 使用数据属性将HTML数据复制到另一个元素
- 如何选择给定类的上一个元素
- 动态修改一个元素,使其与给定的选择器匹配