用作委托人时传递到 .on 的有效候选项

Valid candidates for passing into .on when used as delegator

本文关键字:候选项 有效 选项 on 委托人      更新时间:2023-09-26

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 对象,我将不得不再次提供一个选择器(让它再次执行整个选择过程(,而不是能够使用我已经完成的操作,这似乎很愚蠢......?

委派有两个目的:

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

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

现在,回答您的问题:

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

  2. 你说:

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

    这是一个错误的假设。您始终绑定到要调用.on的元素。您传递的选择器仅用于检查它是否与浏览器提供的事件对象的 currentTarget 属性匹配。

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

  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(又名 event.currentTarget(。我不确定为什么使用 jQuery 对象和 DOM 节点会得到不同的结果。