获取通过父级绑定到元素的函数列表(通过.on())

时间:2014-06-11 03:48:23

标签: javascript jquery javascript-events

我正在尝试使用jQuery&{39} $._data() seen here获取附加到元素的事件列表,但我找不到API中任何文档的链接。如何获取绑定到我的元素的函数的名称?我没有在返回的数据中看到它。此外,如果函数实际上绑定到父元素,如果我只有孩子,是否仍然可以访问函数名称?当然这些必须通过jQuery存储在内部。

var fnPar = function(){
  alert("test");
};
var fnChl = function(){
  alert("test");
};
$(function(){


  $("body").on("click", "#par", function(){

    fnPar();

  });  

  $("#par").on("click", "#chl", function(){

    fnChl();

  });

  console.log($._data($('#par')[0], 'events'));
  console.log($._data($('#chl')[0], 'events'));

});

2 个答案:

答案 0 :(得分:4)

我的问题中有两部分我会尝试回答。第一个问题:

  

如何获取绑定到元素的函数名称?

这个是相当直接的,你实际上是在你的小提琴的正确道路上。绑定事件处理程序时,处理程序的事件类型将添加到jQuery的内部_data对象中。所以,例如,如果你这样做:

$('div').on('click', function() { ... })

然后在内部,jQuery将创建一个对象{}并向其添加一个键click。像这样:

{'click': []}

关键点指向一组对象,这些对象是您使用click类型绑定的所有事件处理程序。

如果你要添加这样的自定义事件:

$('div').on('myfancyhandler', function() {...})

并调用$._data($('div')[0], 'events'),您会看到一个返回的对象:

{'myfancyhandler': []}

因此,当您调用$._data( el , 'events')时,您可以访问处理程序属性(指向处理程序的数组),如下所示:

// Bind two event handlers - click and our custom myfancyhandler event
$('div').on('click myfancyhandler', function() { });

// Returns object {click: [], myfancyhandler: []}
var handlers = $._data($('div')[0], 'events');

// Access handler (function passed for callback)
var handler = handlers.click[0].handler; // dot notation, square bracket works too

现在,假设你做了这样的事情:

$('div').on('click', function(){ alert(1) });
$('div').on('click', function(){ alert(2) });

var handlers = $._data($('div')[0], 'events');

_data对象将有一个click属性,其中包含数组中的两个项目,如下所示:

{click: [
    {
        handler: function() { alert(1) }
        /* additional properties */
    },
    {
        handler: function() { alert(2) }
        /* additional properties */
    }
]}

在视觉上(在我们的控制台中),您可以看到第一个对象是警报1的函数,第二个函数警告2.但是,如果您需要以编程方式检查,该怎么办?为此,我们需要将anonymous functions命名为:{/ p>

$('div').on('click', function alert1(){ alert(1) });
$('div').on('click', function alert2(){ alert(2) });

var handlers = $._data($('div')[0], 'events');

哪会让我们回复:

{click: [
    {
        handler: function alert1() { alert(1) }
        /* additional properties */
    },
    {
        handler: function alert2() { alert(2) }
        /* additional properties */
    }
]}

然后我们可以检查(并得到名称):

var handlers = $._data($('div')[0], 'events');
handlers.click.forEach(function(obj, idx){
    console.log(obj.handler.name);
});

那会输出:

<强>控制台
> alert1
> alert2

此外,您可以传递对此函数的引用,如下所示:

function ourCoolHandler() { .. does something .. }

// Bind our cool handler
$('div').on('keyup', ourCoolHandler);

// Get event object
var evtObj = $._data($('div')[0], 'events')

// Get function name from handler object
console.log(evtObj.keyup[0].handler.name) // ourCoolHandler

关于你的第二个问题,即:

  

另外,如果函数实际上绑定到父元素,那么如果我只有子元素,是否仍然可以访问函数名称?

我认为你指的是jQuery的event delegation。像这样:

$('#parentElement').on('click', '#childElement', function() { .. do something } );

然后以某种方式获得基于#childElement命名的函数。简短的回答是否定的,这是不可能做到的。当你说Surely these must be stored internally somewhere by jQuery.

时,你就对了

事实上,让我们来看看当我们这样做时会发生什么:

$('#parentElement').on('click', '#childElement', function doSomething() { .. do something } );

jQuery找到#parentElement并注册一个点击处理程序。但是,它看到您只想在selector#childElement时处理点击事件。 (如果省略,则始终触发事件。)现在,如果我们执行以下操作:

$._data($('#childElement')[0], 'events');

什么都不会被退回。但是,如果我们这样做:

$._data($('#parentElement')[0], 'events');

使用我们的点击处理程序返回一个对象。看起来像这样:

{
    click:
        // 0 index array
        0: {
            handler: function doSomething,
            selector: '#childElement'
        }
        delegateCount: 1
}

正如您在返回的对象中看到的那样,这是jQuery存储子元素的位置。当delegateCount大于0时会过滤这些事件,并会针对传入的selector对其进行过滤。

现在我说的简短回答是否定的。更长的答案是你可以 - 你可以(理论上)遍历DOM并检查每个元素以查看它是否具有事件对象,具有delegateCount,以及选择器是否与子元素匹配。但是,这需要很多逻辑来实现。

最后,最后一招:您可以在Chrome Developer Tool中看到绑定到元素的所有事件处理程序。打开它,单击一个元素,然后选择&#34;事件监听器&#34;选项卡在右侧。如果绑定了一个事件处理程序,它应该显示在那里。像这样:

enter image description here

祝你好运!

答案 1 :(得分:0)

它们存储在handler对象中。 handler.on(events, handler)

的后半部分

可以通过以下方式访问:

var functionNameGoesHere = function () {
    alert("test");
};
$(function () {
    $("#par").on("click", function () {
        functionNameGoesHere();
    });

    var elem = $('#par')[0];
    var data = jQuery.hasData( elem ) && jQuery._data( elem );
    console.log(data.events.click[0].handler); //function() {functionNameGoesHere();}
});

小提琴: http://jsfiddle.net/KyleMuir/DHF4a/

有关抽出与元素相关的所有事件的所有处理程序的更通用方法,请查看以下答案:Accessing functions bound to event handlers with jQuery