香草JavaScript事件代表团 [英] Vanilla JavaScript Event Delegation

查看:113
本文介绍了香草JavaScript事件代表团的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在vanilla js中进行事件委托的最佳方式(最快/正确)是什么?

What is the best way ( fastest / proper ) fashion to do event delegation in vanilla js?

例如,如果我在jQuery中有这个:

For example if I had this in jQuery:

$('#main').on('click', '.focused', function(){
    settingsPanel();
});

如何将其翻译为vanilla js?也许用 .addEventListener()

How can I translate that to vanilla js? Perhaps with .addEventListener()

我能想到这样做的方式是:

The way I can think of doing this is:

document.getElementById('main').addEventListener('click', dothis);
function dothis(){
    // now in jQuery
    $(this).children().each(function(){
         if($(this).is('.focused') settingsPanel();
    }); 
 }

但这似乎效率低下,特别是如果 #main 有很多孩子。

But that seems inefficient especially if #main has many children.

这是正确的方法吗?

document.getElementById('main').addEventListener('click', doThis);
function doThis(event){
    if($(event.target).is('.focused') || $(event.target).parents().is('.focused') settingsPanel();
}


推荐答案

我想出了一个简单的解决方案 ,这似乎工作得很好(尽管有传统的IE支持)。我们扩展 EventTarget 的原型,以提供 delegateEventListener 方法d使用以下语法:

I've come up with a simple solution which seems to work rather well (legacy IE support notwithstanding). Here we extend the EventTarget's prototype to provide a delegateEventListener method which works using the following syntax:

EventTarget.delegateEventListener(string event, string toFind, function fn)

我创建了一个相当复杂的 小提琴 来演示它在行动中,我们委托绿色元素的所有事件。停止传播继续工作,您可以访问 event.currentTarget 这个(与jQuery一样)。

I've created a fairly complex fiddle to demonstrate it in action, where we delegate all events for the green elements. Stopping propagation continues to work and you can access what should be the event.currentTarget through this (as with jQuery).

这是完整的解决方案:

(function(document, EventTarget) {
  var elementProto = window.Element.prototype,
      matchesFn = elementProto.matches;

  /* Check various vendor-prefixed versions of Element.matches */
  if(!matchesFn) {
    ['webkit', 'ms', 'moz'].some(function(prefix) {
      var prefixedFn = prefix + 'MatchesSelector';
      if(elementProto.hasOwnProperty(prefixedFn)) {
        matchesFn = elementProto[prefixedFn];
        return true;
      }
    });
  }

  /* Traverse DOM from event target up to parent, searching for selector */
  function passedThrough(event, selector, stopAt) {
    var currentNode = event.target;

    while(true) {
      if(matchesFn.call(currentNode, selector)) {
        return currentNode;
      }
      else if(currentNode != stopAt && currentNode != document.body) {
        currentNode = currentNode.parentNode;
      }
      else {
        return false;
      }
    }
  }

  /* Extend the EventTarget prototype to add a delegateEventListener() event */
  EventTarget.prototype.delegateEventListener = function(eName, toFind, fn) {
    this.addEventListener(eName, function(event) {
      var found = passedThrough(event, toFind, event.currentTarget);

      if(found) {
        // Execute the callback with the context set to the found element
        // jQuery goes way further, it even has it's own event object
        fn.call(found, event);
      }
    });
  };

}(window.document, window.EventTarget || window.Element));

这篇关于香草JavaScript事件代表团的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆