触发器单击事件:未触发addEventListener

时间:2017-11-28 15:07:33

标签: javascript jquery

我想知道为什么在jQuery addEventListener("click", function(){})触发时没有调用.trigger("click"),但是在dispatchEvent(new Event("click"))触发时调用它。

var el = document.getElementById("foo");

$(el).click(function() { console.log("jquery click"); });
el.onclick = function() { console.log("onclick"); };
el.addEventListener("click", function() { console.log("addEventlistener click"); });

$(el).trigger("click");
console.log("--------");
el.dispatchEvent(new Event("click"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#foo" id="foo">foo</a>

这会产生以下控制台输出

(index):54 jquery click
(index):55 onclick
(index):59 --------
(index):54 jquery click
(index):55 onclick
(index):56 addEventlistener click

我错过了什么吗? jQuery是否通过直接调用它的事件监听器来“伪造”一次点击?

2 个答案:

答案 0 :(得分:5)

jQuery的trigger触发jQuery处理程序并调用元素上的.event()函数* - 除非它是click元素上的a ,在这种情况下,它不会做第二部分。 (它还特别对待复选框。)例如,如果我们在您的示例中使用div,我们会看到它:

var el = document.getElementById("foo");

$(el).click(function() { console.log("jquery click"); });
el.onclick = function() { console.log("onclick"); };
el.addEventListener("click", function() { console.log("addEventlistener click"); });

$(el).trigger("click");
console.log("--------");
el.dispatchEvent(new Event("click"));
<div id="foo"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

...但不在a上:

var el = document.getElementById("foo");

$(el).click(function() { console.log("jquery click"); });
el.onclick = function() { console.log("onclick"); };
el.addEventListener("click", function() { console.log("addEventlistener click"); });

$(el).trigger("click");
console.log("--------");
el.dispatchEvent(new Event("click"));
<a href="#foo" id="foo">foo</a>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

为什么不呢?对于“跨浏览器一致性”,消息来源说:请参阅https://github.com/jquery/jquery/blob/master/src/event.js#L476(该链接是一个行号,因此可能会腐烂):

    click: {

        // For checkbox, fire native event so checked state will be right
        trigger: function() {
            if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
                this.click();
                return false;
            }
        },

        // For cross-browser consistency, don't fire native .click() on links
        _default: function( event ) {
            return nodeName( event.target, "a" );
        }
    },

注意最后一点。

*找到这个有点棘手。 trigger says

  

当相应的事件发生时,会触发任何事件处理程序附加.on()或其中一种快捷方法。但是,可以使用.trigger()方法手动触发它们。

...但是triggerHandler says

  

此方法的行为类似于.trigger(),但以下情况除外:

  • .triggerHandler( "event" )方法不会在触发的元素上调用.event()。这意味着表单上的.triggerHandler( "submit" )不会在表单上调用.submit()
  • 虽然.trigger()将对jQuery对象匹配的所有元素进行操作,但.triggerHandler()仅影响第一个匹配的元素。
  • 使用.triggerHandler()触发的事件不会冒出DOM层次结构;如果他们没有被目标元素直接处理,他们什么都不做。
  • .triggerHandler()不返回jQuery对象(允许链接),而是返回它导致执行的最后一个处理程序返回的任何值。如果没有触发处理程序,则返回undefined

在这一点上肯定会更清楚。

答案 1 :(得分:0)

trigger()一直是我的问题。

API说:

  

执行所有处理程序以及附加到匹配元素的行为   对于给定的事件类型。

http://api.jquery.com/trigger/

addEventListener的行为与内联点击事件不同,浏览器会以不同的方式解释泡泡: https://www.w3.org/TR/DOM-Level-3-Events/#event-flow

当您发送时,您正在创建一个绕过这些限制的自定义事件: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

因此,dispatch可以解决这些限制,而trigger()会尝试为您完成这项工作。