为什么jQuery triggerHandler()有效,但是trigger()没有?

Mis*_*hko 2 javascript jquery javascript-events jquery-trigger jquery-triggerhandler

使用triggerHandler()作品单击元素:

$element = $('#gwt-debug-location-pill-edit-div:visible');
$element.triggerHandler('click');
Run Code Online (Sandbox Code Playgroud)

但是,使用它来点击它trigger()不会:

$element.trigger('click');
Run Code Online (Sandbox Code Playgroud)

这是为什么?


要复制它(在Firefox和Chrome中):

  • 转到https://adwords.google.cn/select/home,然后使用您的凭据登录
  • 工具和分析->关键字规划师
  • 展开"输入或上传关键字以查看其效果"
  • 使用浏览器的控制台,尝试通过上面的两种方法单击位置框(在下面的屏幕截图中用红色标记)(你需要将jQuery注入页面.我使用jQuerify来做到这一点.)

在此输入图像描述

Ash*_*she 19

让我们比较jQuery.fn.triggerjQuery.fn.triggerHandler:

trigger: function( type, data ) {
    return this.each(function() {
        jQuery.event.trigger( type, data, this );
    });
},
triggerHandler: function( type, data ) {
    var elem = this[0];
    if ( elem ) {
        return jQuery.event.trigger( type, data, elem, true );
    }
}
Run Code Online (Sandbox Code Playgroud)

唯一的区别是第四个参数,true,给予jQuery.event.triggertriggerHandler.

看一下jQuery.event.trigger,该论点被称为onlyHandlers,除其他外,还有以下triggerHandler注释的文档:

  • .triggerHandler()方法不会导致事件的默认行为(例如表单提交).

我们可以看到实际触发默认行为的位置:

// If nobody prevented the default action, do it now
if ( !onlyHandlers && !event.isDefaultPrevented() ) {
Run Code Online (Sandbox Code Playgroud)

如果onlyHandlers是false(trigger()),并且没有事件处理程序停止执行默认事件,则将执行默认操作.

如果onlyHandlers是真(triggerHandler()),这将永远不会发生.

因此,对于trigger()情况下,它最终执行click()目标元素,这会触发状态变化上正确,但事实证明,在这两个trigger()triggerHandler()的情况下,点击是已经正确地发射了通过上面的eventPath循环:

// Native handler
handle = ontype && cur[ ontype ];
if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
Run Code Online (Sandbox Code Playgroud)

所以trigger('click')最后点击元素两次(!) - 大概是因为click()没有返回false,所以从不阻止事件默认操作 - 而triggerHandler('click')只是一次.

这可以通过jQuery.event.trigger使用检查器单步执行该方法并查看选择器打开然后再次关闭来验证.

问题是这是否是我们通常所期望的; 看起来奇怪的是,在仅有DOM反应的情况下,否则工作的事件触发器会导致双触发器.