单用户操作触发两个事件-第二个事件不触发't触发器

Single user action firing two events - second event doesn't trigger

本文关键字:事件 触发器 第二个 用户 操作 两个 单用户      更新时间:2023-09-26

我遇到了这个问题,用户的一个操作应该触发两个事件,但它只触发第一个事件。

场景:

用户将一些文本输入到一个特殊字段中,该字段在聚焦时修改布局,在输入文本后,在不离开字段的情况下,他们单击一个按钮。

发生了什么

我在一个文本框上有一个focusout事件,然后单击按钮上的事件。我看到的是focusout事件被触发,但click事件从未触发。

我把它封装在一个jsfiddle中:

http://jsfiddle.net/fCz6X/13/

$('#theText').focusout(function (){
    $("#focusevent").text("Focusevent");
    console.log("focus");
});
$('#theButton').click(function (){
    $("#clickevent").text("Clickevent");
    console.log("click");
});

因此,如果你点击文本字段,然后点击按钮,我希望两个事件都会触发,但我们只看到焦点突出事件。

我对此进行了临时修复,让mousedown事件触发按钮而不是点击事件(这在focusout事件之前触发(,但这会导致一些我不想看到的其他行为和问题。正因为如此,我认为最佳解决方案是找到一种方法,让焦点和点击事件同时发生。有人想过如何解决这个问题吗?

编辑:在看到最初的回应后,我更深入地研究了一下,这里的问题是focusout事件正在改变页面布局,这会稍微按下按钮的位置。点击事件在聚焦完成后触发,但由于按钮不再位于完全相同的位置,因此不会发生任何事情。

这是一个更新的小提琴,显示了我的问题http://jsfiddle.net/fCz6X/11/

这是因为您正在调用alert-focusout事件触发,但在浏览器识别出您单击了按钮之前,警报框会阻止它。

将您的事件处理程序更改为console.log或其他不显眼的东西,您就可以了。

是Alert在阻止。某些浏览器安全性可防止一次启动过多的窗口。警告。

当尝试使用其他触发器时,它看起来很像。您可以尝试console.log()

$('#theText').on("focusout",function (){
    $("#theText").val($("#theText").val()+"flb");   
});
$('#theButton').on("click",function (){
    $("#theText").val($("#theText").val()+"but");
});

我认为这是因为focusout事件首先触发,执行处理程序,然后alert阻止浏览器识别点击。

console.log而不是alert再试一次——它的侵入性较小。

正如Joe所说,阻塞警报调用是破坏事件的原因。使用非阻塞调用,您将看到这两个事件。

如果你真的需要执行这样的警报,你可以使用setTimeout((推迟调用"警报">

$('#theText').focusout(function (){
    setTimeout(function() { // alert after all events have resolved
        alert("focus left text box");
    }, 0);
});

编辑:在您更新的fiddle中,点击事件从不触发的原因是没有发生点击事件。如果您在mousedown上将按钮从鼠标下方移出,则不会有后续的mouseup,这就是启动"单击"事件的原因。

您可能需要重新考虑设计的其他方面。您使用"mousedown"的解决方案是您所能达到的最佳解决方案,因为它是唯一实际发生的事件。

我遇到过类似的问题,focusout函数似乎阻止了click事件的启动。

click事件由mousedownmouseup两个事件组成。如果单击调用前一个元素的focusout,则focusoutevent发生在后续元素的mousedownevent之后和mouseup事件之前。

在我的情况下,我的focusout函数使用fetch API调用一个操作,在此期间,动画图像将显示在覆盖上。覆盖阻止了为原始元素注册mouseup事件,因此只注册了mousedown活动;没有生成点击事件。

我的解决方案是(1(设置一个全局变量,保留对单击的原始元素的引用;(2(向图像覆盖添加一个mouseup侦听器(其id为"wait"(,以调用原始元素的click方法(在那些在覆盖仍然可见的情况下释放单击(:

调用fetch API包装器的focusout事件调用的函数必须包含其相关元素作为参数:

// function called by a focusout event
function myResponse(e) {
  myRequest = 'whatever';
  return myFetch('save.php', myRequest, true, e.relatedTarget).then(response => {
...
}

单击的元素被设置为全局变量:

let relatedTarget;
// simulate the original click
function finishClick(e) {
  if (relatedTarget) {
    relatedTarget.click();
    relatedTarget = null;
  }
}
// but not if both mousedown and mouseup registered on the overlay
function unsetRelatedTarget(e) {
  relatedTarget = null;
}
// custom wrapper for fetch API
async function myFetch(page, request, wait, relatedTargetParam) {
  if (wait) {
    wait = document.getElementById('wait');
    if (wait) {
      wait.style.display = 'block';
      if (relatedTargetParam) {
        relatedTarget = relatedTargetParam;
        wait.addEventListener('mousedown', unsetRelatedTarget);
        wait.addEventListener('mouseup', finishClick);
      }
    }
  }
  return await fetch(page,
    {
      method: 'POST',
      body: request
    }
  ).then(response => {
...

另一种解决方案是,当focusout事件可能中断单击时,仅使用mousedown活动,而不是click。此解决方案的一个缺点是,用户不能再通过在释放单击器之前将鼠标从元素移开来中止单击事件。