【问题标题】:Binding multiple events to a listener (without JQuery)?将多个事件绑定到侦听器(没有 JQuery)?
【发布时间】:2012-02-06 11:50:47
【问题描述】:

在处理浏览器事件时,我开始为移动设备整合 Safari 的 touchEvents。我发现addEventListeners 正在与条件叠加。 这个项目不能使用 JQuery。

标准事件监听器:

/* option 1 */
window.addEventListener('mousemove', this.mouseMoveHandler, false);
window.addEventListener('touchmove', this.mouseMoveHandler, false);

/* option 2, only enables the required event */
var isTouchEnabled = window.Touch || false;
window.addEventListener(isTouchEnabled ? 'touchmove' : 'mousemove', this.mouseMoveHandler, false);

JQuery 的bind 允许多个事件,如下所示:

$(window).bind('mousemove touchmove', function(e) {
    //do something;
});

有没有办法像 JQuery 示例那样组合两个事件侦听器? 例如:

window.addEventListener('mousemove touchmove', this.mouseMoveHandler, false);

感谢任何建议或提示!

【问题讨论】:

  • @RobG 可能是因为问题是询问如何复制 jQuery 的一些功能。我不确定这是否适合用于标签。
  • 很公平,在我看来,这个问题不需要它。不过看起来有点刻薄,已删除。

标签: javascript jquery touch addeventlistener


【解决方案1】:

实现预期结果的一些紧凑语法,POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });

【讨论】:

  • 或直接['mousemove', 'touchmove'].forEach(...)
  • +1 而且它不需要«ECMAScript 2015 箭头函数»扩展! ;-)
  • @zuckerburg 首先,不是硬编码数组,而是硬编码字符串然后拆分它,你真的确定这是要走的路吗?你确定这是最易读的写法吗? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); 不仅可读性更高,而且速度更快,无需拆分字符串,然后为结果数组中的每个项目运行一个函数。
  • @IharobAlAsimi 这段代码是 4 年前写的,当时我发现了我的空格键。字符串拆分与 OP 对字符串的使用有关
  • @IharobAlAsimi 我没有编写代码。你说它不可读。显然这不是因为你和我都能够阅读代码。这就像争论语法一样。 99% 的程序员都能很好地阅读代码
【解决方案2】:

在 POJS 中,您一次添加一个侦听器。为同一元素上的两个不同事件添加相同的侦听器并不常见。您可以编写自己的小函数来完成这项工作,例如:

/* Add one or more listeners to an element
** @param {DOMElement} element - DOM element to add listeners to
** @param {string} eventNames - space separated list of event names, e.g. 'click change'
** @param {Function} listener - function to attach for each event as a listener
*/
function addListenerMulti(element, eventNames, listener) {
  var events = eventNames.split(' ');
  for (var i=0, iLen=events.length; i<iLen; i++) {
    element.addEventListener(events[i], listener, false);
  }
}

addListenerMulti(window, 'mousemove touchmove', function(){…});

希望它显示了这个概念。

编辑 2016-02-25

Dalgard 的评论让我重新审视了这一点。我想在一个元素上为多个事件添加相同的侦听器现在更常见,以涵盖正在使用的各种接口类型,并且 Isaac 的答案提供了一个很好的使用内置方法来减少代码(尽管代码本身更少,不一定是奖金)。用 ECMAScript 2015 扩展箭头函数给出:

function addListenerMulti(el, s, fn) {
  s.split(' ').forEach(e => el.addEventListener(e, fn, false));
}

类似的策略可以将相同的侦听器添加到多个元素,但这样做的需要可能是事件委托的一个指标。

【讨论】:

  • 谢谢你的句子"It is not common to add the same listener for two different events on the same element." 有时(更环保的)开发人员需要听到这个才能知道他们做得对:)
  • 你不是说“这并不罕见”吗?
  • @dalgard——现在触摸设备更常见了,但仅限于有限数量的事件(例如 mousemove 和 touchmove)。必须显示以物理项目命名事件的短视,指针移动可能更合适。它可以通过触摸或其他设备来实现。在老鼠(或老鼠)之前有 x/y 轮,我用过的一些有手轮和脚轮(1970s Stecometer)。还有跟踪球和球体,有些是 3d 移动的。
  • @RobG:我正在处理的 API 是 DOM,是的,它的缺点很多 :) 但它也可能只是避免在类似的侦听器中重复代码的问题。
  • @PedroFerreira——是的,当然,目前使用的浏览器中可能有一半以上不支持箭头功能,但它们玩起来很有趣,而且总是有Babel。 ;-)
【解决方案3】:

清理艾萨克的回答:

['mousemove', 'touchmove'].forEach(function(e) {
  window.addEventListener(e, mouseMoveHandler);
});

编辑

ES6 辅助函数:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}

【讨论】:

  • 仅供参考:map != forEach
【解决方案4】:

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));

【讨论】:

  • 或者使用for...of 循环
【解决方案5】:

对我来说;此代码运行良好,是使用相同(内联)函数处理多个事件的最短代码。

var eventList = ["change", "keyup", "paste", "input", "propertychange", "..."];
for(event of eventList) {
    element.addEventListener(event, function() {
        // your function body...
        console.log("you inserted things by paste or typing etc.");
    });
}

【讨论】:

  • 正是我想要的。谢谢!
【解决方案6】:

我有一个更简单的解决方案:

window.onload = window.onresize = (event) => {
    //Your Code Here
}

我已经对此进行了测试,它运行良好,另一方面,它像这里的其他示例一样紧凑且简单。

【讨论】:

  • 只有一个 .onload 可能。也许你覆盖了一个老听众。根据您的环境,这可能是个问题。
【解决方案7】:

一种方法:

const troll = document.getElementById('troll');

['mousedown', 'mouseup'].forEach(type => {
	if (type === 'mousedown') {
		troll.addEventListener(type, () => console.log('Mouse is down'));
	}
        else if (type === 'mouseup') {
                troll.addEventListener(type, () => console.log('Mouse is up'));
        }
});
img {
  width: 100px;
  cursor: pointer;
}
<div id="troll">
  <img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>

【讨论】:

  • 如果你要做if (type === 'mousedown')?!?!
  • @Arad 因为您只能使用该语句,因为typeforEach() 的参数。因此,如果没有数组和 forEach 函数,type 将不会被定义。
  • 不,我的意思是为什么不直接做troll.addEventListener('mousedown', () =&gt; console.log('Mouse is down'));。如果您要检查每种事件类型并为其附加不同的事件处理程序,为什么需要forEach?!在这种情况下,使用forEach 的全部意义在于将同一个事件处理程序附加到多个事件,显然。
【解决方案8】:

AddEventListener 采用表示event.type 的简单字符串。所以你需要编写一个自定义函数来迭代多个事件。

这是通过使用 .split(" ") 在 jQuery 中处理的,然后遍历列表以设置每个 types 的 eventListeners。

    // Add elem as a property of the handle function
    // This is to prevent a memory leak with non-native events in IE.
    eventHandle.elem = elem;

    // Handle multiple events separated by a space
    // jQuery(...).bind("mouseover mouseout", fn);
    types = types.split(" ");  

    var type, i = 0, namespaces;

    while ( (type = types[ i++ ]) ) {  <-- iterates thru 1 by 1

【讨论】:

    【解决方案9】:

    您还可以使用原型将自定义函数绑定到所有元素

    Node.prototype.addEventListeners = function(eventNames, eventFunction){
        for (eventName of eventNames.split(' '))
            this.addEventListener(eventName, eventFunction);
    }
    

    那就用吧

    document.body.addEventListeners("mousedown touchdown", myFunction)
    

    【讨论】:

    • 不赞成修改不是您创建的原型。对于宠物项目,请继续,但请不要在您打算与他人共享的包中执行此操作。
    猜你喜欢
    • 2021-09-28
    • 2015-11-24
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多