Closure事件委托 - DOM父级上的事件侦听器,它覆盖给定类的子级/后代

时间:2013-12-13 23:53:23

标签: javascript jquery event-handling google-closure event-delegation

在jQuery中,您可以执行以下操作:

$('#j_unoffered').on('click', '.icon_del', function () {...

如果点击任何具有类j_unoffered的后代元素,则会在元素icon_del上放置一个处理程序。此外,它适用于任何后续创建的icon_del元素。

我可以在Closure中正常工作,点击在元素本身上。

goog.events.listen(
    goog.dom.getElement('j_unoffered'),  
    goog.events.EventType.CLICK,
    function(e) {...

如何以与jQuery示例相同的方式在Closure中指定适用于其子/后代的父事件目标?

我假设我需要以某种方式使用setParentEventTarget,但我不确定如何为DOM事件实现它。我发现的大多数文档都与自定义调度事件有关。

- 更新 -

我想知道这个相当简单的解决方案是否有任何问题:

goog.events.listen(
    goog.dom.getElement('j_unoffered'),  
    goog.events.EventType.CLICK,
    function(e) {
        if (e.target.className.indexOf('icon_del') !== -1) {...

它仍将this绑定到父级,但e.target允许解决方法。 listen(opt_handler)中的第五个参数允许您将this绑定到其他内容,所以我猜这也是一个途径。

2 个答案:

答案 0 :(得分:5)

我也不知道这种可能性,所以我建议其他代码:

var addHandler = function(containerSelector, eventType, nestSelector, handler) {
    var parent = goog.isString(containerSelector) ? 
                 document.querySelector(containerSelector) :
                 containerSelector;

    return goog.events.listen(
        parent,
        eventType,
        function(e) {

            var children = parent.querySelectorAll(nestSelector);
            var needChild = goog.array.find(children, function(child) {
                return goog.dom.contains(child, e.target);
            });

            if (needChild)
                handler.call(needChild, e);                

        });
});

用法:

addHandler('#elem', goog.events.EventType.CLICK, '.sub-class', function(e) {
    console.log(e.target);
});

<强>更新

如果您将使用此e.target.className.indexOf('icon_del'),则可能会错过正确的事件。考虑一个id = container的容器div,它有几个带有类innerContainer的div,每个div包含几个class = finalDiv的div。并且考虑您将使用上面的代码添加事件处理程序,这将检查innerContainer类的e.target。问题是,当用户点击finalDiv时,您的处理程序将被调用,但事件目标将是finalDiv,不是innerContainer,而是由它包含。你的代码会错过它,但不应该。我的代码检查e.target是否有嵌套类或包含它,所以你不会错过这样的事件。

opt_handler也不能真正帮助你,因为你可能会有许多嵌套元素(你会把它们传递到这里?可能全部,但没有那么有用,你可以在事件中得到它们)处理程序,你可以随后动态添加,所以当你添加处理程序时,你无法了解它们。

总之,我认为在事件处理程序中完成这样的工作是合理且最有效的。

答案 1 :(得分:3)

您所指的是event delegation

seems使用Google Closure库这是不可能的(开箱即用);所以我的建议是使用jQuery或其他提供此功能的类似事件处理库。如果这是不可能的,或者你想亲手做到这里是一种可能的方法(注意:这不是生产用途)

var delegateClick = function(containerId, childrenClass, handler){
  goog.events.listen(goog.dom.getElement(containerId), goog.events.EventType.CLICK, function(event){
    var target = event.target;
    //console.log(event);
    while(target){
      if ( target.className && target.className.split(" ").indexOf(childrenClass)!== -1) {
        break;
      }
      target = target.parentNode;
    }
    if(target){
      //handle event if still have target
      handler.call(target, event);
    }
  });
}
//then use it, try this here: http://closure-library.googlecode.com/git/closure/goog/demos/index.html
//..select the nav context
delegateClick( 'demo-list' ,'goog-tree-icon', function(event){console.log(event);})

以下是对event delegation

的更深入分析

同样,您应该使用经过验证的库,以下是一些选项:jQueryZeptoBean