当用作委托人时,有效的候选人进入.on

时间:2013-05-24 14:53:12

标签: javascript jquery

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对象,我必须再次提供一个选择器(让它再次完成整个选择过程),而不是能够使用我已经完成的工作......?

2 个答案:

答案 0 :(得分:3)

代表团有两个目的:

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

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

现在,回答你的问题:

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

  2. 你说:

      

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

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

  3. 我在#2中所说的同样适用于:jQuery不会根据你传递的选择器选择任何东西,它只会检查当前选择的currentTarget。

答案 1 :(得分:2)

  1. 要回答您的主要问题,不,选择器应该是字符串,或undefined。您所看到的是jQuery如何尝试猜测您正在使用哪种调用约定的怪癖 - 稍后会对此进行更多介绍。

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

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

  4. 您可以通过多种方式调用.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节点获得不同的结果。