不要在已经触发另一个事件的情况下再触发一个事件。

6

我有这样的一段代码:

$('#foo').on('click', function(e) {
   //do something
});

$('form input').on('change', function(e) {
  //do some other things
));

第一个和第二个事件实际上使用相同的输入字段进行相同的操作,但方式不同。问题是,当我点击#foo元素时,表单更改元素也会触发。我需要在输入内容更改时始终触发表单更改,但不在点击#foo元素时触发。

这就是问题所在。如何解决?

以下是jsfiddle上的代码:http://jsfiddle.net/QhXyj/1/


我同意,点击操作不应触发相同元素的变化。 - charlietfl
@charlietfl:确实如此。如果您单击其他地方,焦点会改变,当输入元素失去焦点时,可能会触发change事件。 - Bergi
@bergi 但是我的意思是不应该在点击的同一输入上进行更改。是的,更改之前处于焦点状态的输入。 - charlietfl
@charlietfl:好的,是的,但这并不会发生。如果您单击聚焦元素,则不会触发更改事件-它只可能更改插入符号。 - Bergi
@Bergi 现在添加了一些代码,我可以看到情况了...最初没有提供任何代码,问题也不清楚,措辞也不明确。 - charlietfl
4个回答

5
发生的情况是当焦点离开#input时,onChange事件被触发。在您的情况下,这与点击按钮同时发生。请尝试先按Tab键,然后再点击按钮。
为处理这种特殊情况,一种解决方案是延迟调用change事件足够长的时间,以检查是否在此期间单击了按钮。实际上,100毫秒有效。以下是代码:
$().ready(function() {

    var stopTheChangeBecauseTheButtonWasClicked = false;
    $('#button').on('click', function(e) {
        stopTheChangeBecauseTheButtonWasClicked = true;
        $('#wtf').html("I don't need to change #input in this case");
    });

    $('#input').on('change', function(e) {
        var self = this;
        setTimeout(function doTheChange() {
            if (!stopTheChangeBecauseTheButtonWasClicked) {
                $(self).val($(self).val() + ' - changed!');
            } else {
                stopTheChangeBecauseTheButtonWasClicked = false;
            }
        }, 100);
    });
});

"而小提琴 - http://jsfiddle.net/dandv/QhXyj/11/"

有一个事件的巧合,当 #input 失去焦点时会触发 onChange 事件。我已经更新了我的答案。 - Dan Dascalescu
它对我有效,但我不能强制用户先取消焦点输入,然后再单击按钮。 - Taras Bulgakov
我现在明白你想做什么了,看看更新后的答案吧! - Dan Dascalescu
我本来想用另一种方式实现,但是我希望有更优美的解决方案,而且不会出现超时问题。但是它能够正常工作:)谢谢! - Taras Bulgakov
这是一个有趣的问题。我已经点赞了它,而且我很好奇是否有人能找到更优雅的答案。 - Dan Dascalescu

1

在模糊元素上的更改事件在单击元素获得焦点之前触发是很自然的。如果您不想使用超时(如Dan所建议的“在输入更改X毫秒后执行某些操作,除非在按钮被单击之间”,而超时很丑陋),那么您只能执行这些操作两次。在输入更改后,保存其状态并执行某些操作。然后 - 在稍后的某个时间 - 单击按钮时,检索保存的状态并执行类似的操作。我想这就是您实际想要的UI行为,因为并非所有用户都那么快。如果有人离开输入框(例如通过按Tab键),然后稍后“独立”激活按钮,您真的想执行这两个操作吗?

var inputval = null, changedval = null;

$('form input').on('change', function(e) {
    inputval = this.value;
    // do some things with it and save them to
    changedval = …
    // you might use the value property of the input itself
));

$('#foo').on('click', function(e) {
    // do something with inputval
});

$('form …').on('any other action') {
    // you might want to invalidate the cache:
    inputval = changedval;
    // so that from now on a click operates with the new value
});

0
$('form input').on('change', function(e) {
  // don't do the thing if the input is #foo
  if ( $(this).attrib('id') == 'foo' ) return;

  //do some other things
));

更新

这样怎么样:

$().ready(function() {

    $('#button').on('click', function(e) {
        $('#wtf').html("I don't need to change #input in this case");
    });

    $('#input').on('change', function(e) {
        // determine id #input is in focus
        if ( ! $(this).is(":focus") ) return;

        $(this).val($(this).val()+' - changed!');
    });  
});

0
$(function() {


          $('#button').on('click', function() {
              //use text() not html() here
              $('#wtf').text("I don't need to change #input in this case");
          }); 

          //fire on blur, that is when user types and presses tab
          $('#input').on('blur', function() {
              alert("clicked"); //this doesn't fire when you click button
              $(this).val($(this).val()+' - changed!');
          });  
      });​

这里是Fiddle


同样的故事 :(. 在你的 Fiddle 中,当我点击按钮时,模糊事件仍然会触发。 - Taras Bulgakov
它没有。我在blur中添加了一个alert()并更新了fiddle。 - Matija Grcic
当输入字段为空时,它不起作用。但是如果我输入了一些内容,然后点击按钮-警报仍然有效。 - Taras Bulgakov
1
这就是blur()事件的本质,只要您将焦点从输入框中移除,它就会被调用。 - Matija Grcic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接