将事件重定向到内部元素

Redirect an event to an inner element

本文关键字:内部 元素 重定向 事件      更新时间:2023-09-26

我有一个特殊的场景,我需要在较高级别捕获关键事件,并将它们重定向到较低级别。我试图写这样的代码,但实际上似乎jQuery是愚蠢地使用完全相同的事件对象,所以target没有改变,所以Maximum callstack size exceeded

$("#outer").on("keydown", function(evt) {
  if (evt.target !== $("#inner")[0] && !$.contains($("#inner")[0], evt.target)) {
    $("#inner").trigger(evt);
  }
});

带有示例标记

<div id="#outer">
  <div id="#inner">
  </div>
</div>

事件重定向到另一个元素的正确方法是什么?我当然可以手动"黑"target,但它是安全的吗?

我正在研究一个插件,它动态地显示一个菜单作为一个弹出窗口或基于屏幕大小的模态。如果我有一个模态,我需要这个键重定向。消费者不应该知道它是弹出式还是模式式。我使用bootstrap的模态插件,它捕获关键事件,因为一个"焦点锁定的东西",所以我可以使它透明的唯一方法是我重定向这些事件到我的真正的菜单。

您可以将事件处理程序附加到外部,并指定要使用的选择器来匹配事件:

$('#outer').on('keydown', '#inner', event => {
  /* this is executed when #inner is clicked */
});

如果你真的想使用触发器,你可以把它放在setTimeout:

$('#outer').on('keydown', event => {
  if (yourCondition) {
    setTimeout(() => $('#inner').trigger(event), 0);
  }
});

事件将弹出,你是对的,这是同一个事件。这不是jQuery的事情,而是javascript的工作原理。您可能希望在子元素上设置侦听器,并使用preventDefault();

$("#outer").on("keydown", doSomeThing);
$("#inner").on("keydown", doSomeThingElse);
function doSomeThing(e) {
}
function doSomeThingElse(e) {
   e.preventDefault();
}

感谢大家的回答和评论。你们中的一些人建议防止在#innerdiv中传播事件。我需要避免这种情况,我需要一种方法,让任何外部消费者都能看到这个事件,就像它是由#inner元素真正触发的一样。

在此期间,我挖掘了jQuery源代码,并在trigger中找到了这一行。

if ( !event.target ) {
    event.target = elem;
}

因此,当jQuery初始化要触发的事件时,如果target尚未指定,它只会将元素赋值给target。对于这种行为,他们肯定有一些很好的理由,只是目前我看不出来。

所以我能想到的最好的东西就是这样的一个函数

function redirectEvent(currentTarget, evt, newTarget) {
  if (currentTarget !== newTarget && !$.contains(currentTarget, newTarget)) {
    evt = $.Event(evt.type, evt);
    delete evt.target;
    $(newTarget).trigger(evt);
  }
}

就第一次测试而言,我没有看到任何副作用或缺点。