【问题标题】:jQuery change and click event timingjQuery改变和点击事件计时
【发布时间】:2013-01-07 15:36:45
【问题描述】:

我的 jQuery 更改和单击事件似乎存在时间问题。在我的站点中,我使用 Ajax 帖子而不是警报,但使用警报更容易重现它。我有一个使用 jQuery 版本 1.7.1 的简​​单 HTML 页面。

场景是编辑文本框,然后直接单击按钮。 change 事件总是被触发,但如果它包含一个警报,则永远不会调用 click 事件。如果我作弊并在警报周围设置了超时(您可能需要对那里的值进行一些调整),则通常会调用 click 事件。

/** 编辑 **/ 如果您在更改事件中的某处设置断点并等待几秒钟,则单击事件也将无法触发。

<script type="text/javascript">
$(document).ready(function ()
{
    $("input[type=text]").change(function () {
        //alert('changed');

        $("#text").text('changed');

        setTimeout(function () {
            $("#text").text('changed timeout');
            alert('changed');
        }, 100);

    });

    $("input[type=submit]").click(function () {
        alert('clicked');
        $("#text").text('clicked');
    });
});
  </script>
  <div id="main">
    <div class="container">
        <input type="text" />
        <input type="submit" value="click me" />
        <div id="text" >bla</div>
    </div>
  </div>

具有保存行为的 Ajax 调用如下:

$.ajax({
        type: 'POST',
        url: postUrl,
        data: form.serialize(),
        beforeSend: function () {
            // display overlay for work in progress
        },
        success: function (result) {
            updateTableSuccess();
        },
        complete: function () {
            // hide overlay for work in progress
        },
        error: function (jqXHR) {
            if (jqXHR.responseText.length > 0) {
                showErrorMessage(jqXHR.responseText);
            }
        }
    });

叠加层只是将 2 个 div 附加到 body 标签。

/** 编辑 **/ 似乎覆盖是真正的问题,并导致与警报相同的行为并停止触发点击事件。

showWorkInProgress = function (message, elementId)
{
    if ($("#overlay").length == 0)
    {
        $("<div id='overlay' class='ui-widget-overlay'></div>").appendTo("body");
    }

    if ($("#workInProgress").length == 0)
    {
        $("<div id='workInProgress'></div>").appendTo("body");
    }

    $("#workInProgress").html(message);
    if (elementId != null)
    {
        $("#workInProgress").center(elementId);
    }
    else
    {
        $("#workInProgress").center();
    }
    $("#overlay").show();
    $("#workInProgress").show();
};

谁能解释一下为什么 jQuery 会有这样的行为,以及如何在没有 setTimeout hack 的情况下做得更好?

感谢您的帮助 =)

【问题讨论】:

  • 警报与此有什么关系?警报不会改变代码的执行方式,它只会阻止浏览器,直到您单击“确定”。当输入失去焦点时,会发生更改事件,从而导致阻止浏览器的警报框,从而阻止与提交按钮进行交互(我猜)。使用 console.log() 进行调试,或者甚至更好,使用调试器逐行调试。
  • 如果我在 $("#text").text('changed'); 上调试并设置断点并等待几秒钟点击事件也不会被触发。我将为此编辑帖子..
  • 您的代码运行良好。 jsfiddle.net/w9Thc/5 停止卡在警报中。解决真正的问题。
  • 您在使用async: false 处理您的ajax 请求吗?
  • 不,这是默认值,所以是真的。

标签: jquery events timing


【解决方案1】:

Nischo,将您的AJAX 代码插入change 函数时,我无法复制阻塞。如果您希望在提交时触发click 时阻止AJAX,请查看此处。

jQuery - How can I temporarily disable the onclick event listener after the event has been fired?

祝你好运。


在您的解释之后,我确实看到了您所指的内容,因为 change 事件需要失去焦点才能触发您的 click 函数,因为失去焦点是您的点击导致的阻塞而被覆盖。

您可以按照您的说明使用timeOut,也可以在text 输入上重构为keydown 方法。见下文:

$(document).ready(function () 
{
   $("input[type=submit]").click(function () {
      $("#text").text('clicked');
   });

   $("input[type=text]").keydown(function () {
      alert('changed');
      $("#text").text('changed');
   });
});

小提琴: http://jsfiddle.net/9WXBe/2/


尼乔,

在获取您的代码并将其放入 jsFiddle 之后,我看不到更改事件被触发的任何问题。即使代码中有alert

$("input[type=text]").change() 在文本框失去焦点之前不会触发,其他元素如selectradio 将在进行选择或更改后立即执行此操作。

这是小提琴: http://jsfiddle.net/w9Thc/1/

【讨论】:

  • 对不起,我可能不够清楚。问题不是更改事件,而是不再触发的单击事件。更改事件总是被正常触发。
  • 为您更新了上面的解决方案以反映此问题,请使用 keydown()
  • 谢谢,我宁愿不使用 keydown,因为在 ajax 调用中我从数据库中获取数据,它可能不会有这样的最佳性能,否则我会启动 6 个请求并再次中止它们即刻。我仍然不明白的是,如果它只在页面上设置文本但会在大约 10 毫秒后阻止它,为什么它不会阻止事件。
  • 没错,我忘记了整个 AJAX 调用。因此,您计划在此人从框中移开焦点时进行 AJAX 调用,问题是他们通常先单击提交。
  • 是的,没错。我最好的情况是以某种方式知道在调用更改的事件时是否单击了按钮,如果是,甚至不执行 ajax,而只执行单击事件。但我也很乐意稍后中止通话 =)
【解决方案2】:

如果其他人有同样的问题,只是一个简短的回答:问题确实是覆盖整个页面的覆盖,导致与警报相同的行为。

我对此的解释是,更改事件被触发,阻塞 UI,并且 click 事件不能再被触发,因为正如 https://stackoverflow.com/users/1861269/john-gerdsen 所建议的那样。

我为这个问题找到的唯一解决方案是使覆盖层更小,并且只屏蔽真正需要屏蔽的部分。超时也有效,但并非在所有情况下都有效,因为每台机器都有不同的性能。

这可能会帮助任何尝试解决覆盖问题的人: HTML "overlay" which allows clicks to fall through to elements behind it

【讨论】:

    【解决方案3】:

    问题似乎只发生在 Firefox 上。其他浏览器似乎没有问题。我通过重写不使用文本字段更改事件来解决我的问题。不幸的是,我有另一段代码无法做到这一点。更改事件似乎确实阻止了 UI,因为我在“单击”按钮上没有发现任何触发的事件。

    【讨论】:

      猜你喜欢
      • 2015-12-05
      • 1970-01-01
      • 2017-04-14
      • 2012-03-15
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      • 2017-11-14
      相关资源
      最近更新 更多