1

jQuery 文档声明您需要将选择器作为字符串传递给 .on() 方法。例如:

$('#someEl').on('click', '.clickable', function() { /* ... */ });

但是,当您传入单个节点时,它似乎也可以工作:

var someNode = getElementById('someNode');
$('#someEl').on('click', someNode, function() { /* ... */ });

当我尝试传入一个 jQuery 对象时,据我所知,它有点失败,并将其视为直接绑定而不是委托绑定:

var $someNode = $('#someNode');
$('#someEl').on('click', $someNode, function() { /* ... */ });

// seemed to act as:

$('#someEl').on('click', function() { /* ... */ });

所以我想问题是:

  1. 传递一个 DOM 节点不是 API 的记录部分吗?还是我在 API 文档中错过了它?

  2. 缓存节点(不是 jQuery 对象包装节点)是否有好处,或者 jQuery 最终会做同样多的工作吗?(换句话说,我可以假设当我传递一个选择器字符串时,它会解析它,找到有效节点,然后执行绑定......但是如果我为它提供一个漂亮的新鲜 DOM 节点,它会在这个阶段传递,或者它是否仍然出于某种原因在开始工作之前将事情包装在 jQuery 中?)

  3. 我错了 jQuery 对象是一个无效的候选人吗?我只是在测试中错过了什么吗?如果我已经在缓存 jQ 对象,我必须再次提供一个选择器(让它再次完成整个选择过程)而不是能够使用我已经完成的操作,这似乎很愚蠢......?

4

2 回答 2

3

委托有两个目的:

  • 在触发事件时为共享相同逻辑的多个子元素在父元素上设置单个事件处理程序。这应该消耗更少的内存,但只有在用于替换大量单独的事件处理程序时才会产生明显的差异。我怀疑这是你想要达到的目标。

  • 为绑定时 DOM 中不存在的元素定义事件处理程序。

现在,回答您的问题:

  1. 没有记录传递 DOM 节点,因此不应使用它。尽管您说它有效,但 jQuery 正在愚弄您。通过查看源代码,它似乎只是因为事件冒泡而起作用,但this处理程序内部的值将是容器(参见演示)。

  2. 你说:

    我可以假设当我传递一个选择器字符串时,它会解析它,找到有效节点,然后执行绑定

    这是一个错误的假设。您总是绑定到您正在调用的元素(或多个元素).on。您传递的选择器仅用于检查它是否匹配事件对象的currentTarget属性,该属性由浏览器提供。

  3. 我在#2 中所说的同样适用于这里:jQuery 不会根据您传递的选择器选择任何内容,它只会根据该选择器检查 currentTarget。

于 2013-05-24T16:12:07.723 回答
2
  1. 要回答您的主要问题,不,选择器应该是一个字符串,或者undefined. 您所看到的是 jQuery 如何尝试猜测您正在使用的调用约定的一个怪癖——稍后会详细介绍。

  2. 遗憾的是,没有办法传递 DOM 元素而不是选择器。如果delegate是您的处理程序绑定到target的元素,并且是触发事件的元素,jQuery 将始终delegate使用提供的选择器搜索 的后代,并检查是否target在匹配的选择中。如果 jQuery 允许以某种方式传递 DOM 节点而不是选择器,那么肯定会有性能优势。

  3. 好吧,在使用过程中$('#someEl').on('click', '.clickable', handler),您从未选择过匹配的元素.clickable,jQuery 在那个阶段也不会,所以您没有在那里加倍工作。

您可以.on()通过多种方式调用,特别是因为有多个可选参数(选择器、数据)。

当您调用.on(type, notAString, handler)jQuery 时,假定您使用的是调用约定:.on(type, data, handler)- 它转换为.on(type, undefined, data, handler).

这是您建议的调用的演示:http: //jsfiddle.net/BGSacho/HJLXs/1/

HTML:

<div id="someEl">
    <div id="someNode" class="clickable">Click me!</div>
</div>

JavaScript:

$(document).ready(function () {
    function display(event) {
        console.log("event.currentTarget", event.currentTarget);
        console.log("event.delegateTarget:", event.delegateTarget)
        console.log("event.data:", event.data); 
    }
    $('#someEl').on('click', ".clickable", function (event) {
        console.log("I am .on(type, selector, fn) - my currentTarget should be .clickable and my delegateTarget should be #somEl - this demonstrates that jQuery is using the event delegation mechanism. I have no data bound to my event.");
        display(event);
    });

    $('#someEl').on('click', document.getElementById('someNode'), function (event) { 
        console.log("I'm .on(type, data, handler) - my currentTarget should be #someEl because I'm not using a delegation mechanism. I also have some data bound.")
        display(event);
    });

    $('#someEl').on('click', $('#someNode'), function (event) {
        console.log("I'm still .on(type, data, handler)");
        display(event);
    });
});

它们似乎都可以工作,因为您没有在处理代码中使用this(aka event.currentTarget)。我不确定为什么使用 jQuery 对象和 DOM 节点会得到不同的结果。

于 2013-05-24T16:03:21.137 回答