在两个触发事件中阻止函数执行两次

时间:2016-11-16 16:05:26

标签: javascript jquery

我有以下代码:

    myInput.change(function (e) { // this triggers first
        triggerProcess();
    });

    myButton.click(function (e) { // this triggers second
        triggerProcess();
    });

上述问题是当我点击myButton两个事件都被触发并且triggerProcess()被触发两次,这是不希望的。

我只需要triggerProcess()一次点火。我怎么能这样做?

4 个答案:

答案 0 :(得分:2)

Small demo

您可以拥有一个静态标志,一旦发生第一次触发,就会禁用任何更多触发器。可能看起来像这样:

var hasTriggered = false;

myInput.change(function (e) { // this triggers first
  triggerProcess();
});

myButton.click(function (e) { // this triggers second
  triggerProcess();
});

function triggerProcess () {
   // If this process has already been triggered,
   // don't execute the function
   if (hasTriggered) return;

   // Set the flag to signal that we've already triggered
   hasTriggered = true;

   // ...
} 

要重置hasTriggered标记,这完全取决于您以及此程序的工作原理。也许在程序中发生某个事件之后,您想要重新启用再次触发此事件的能力 - 您需要做的就是将hasTriggered标志设置为true。

答案 1 :(得分:1)

你可以使用mousedown事件,它会在输入模糊之前触发,然后检查输入是否有焦点,检查它是否为activeElement,如果它确实有焦点,请不要触发mousedown事件,因为更改事件将触发。

此外,如果您希望在值未更改时发生mousedown事件,并且更改事件未触发,则您还需要检查该事件

var myInput = $('#test1'),
  myButton = $('#test2'),
  i = 0;

myInput.change(function(e) { // this triggers first
  $(this).data('prev', this.value);
  triggerProcess();
});

myButton.mousedown(function(e) { // this triggers second
  var inp = myInput.get(0);
  if (document.activeElement !== inp || inp.value === myInput.data('prev'))
    triggerProcess();
});

function triggerProcess() {
  console.log('triggered : ' + (++i))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="test1">
<br />
<br />
<button id="test2">
  Click
</button>

答案 2 :(得分:0)

使用真实<button>BUTTON</button>。如果您在输入文本上click,则会触发警报,然后一旦您将输入文本留在其他任何位置,那么取消会触发change事件的输入文本,所以现在已经从文本输入中触发了2个事件。

这是一个假设,因为提供的代码远远不足以给出完整和准确的答案。需要HTML以及更多jQuery / JavaScript。 myInputmyButton实际指的是什么,等等?

所以我敢打赌,如果你改变......

  

var myButton = $('{whatever this is}');<input type='button'>

...

  

var myButton = $("button");<button></button>

...你不应该再为一个元素触发两次事件。

这假设triggerProcess()是一个不会操纵事件链或涉及事件的任何其他事情的函数。如果您使用click()change()代替.trigger()triggerHandler()方法,这是一个完全不同的球赛,但它不是。我不确定为什么这么复杂的答案来自一个信息很少的问题......?

顺便说一句,如果myInput是一个搜索框而myButtonmyInput的按钮,正如liben-m所提到的那样,只需删除:

  

myButton.click(...

myButton留作假人。在这种情况下,change事件就足够了。

&#13;
&#13;
var xInput = $('input');
var xButton = $('button'); //«———Add 

xInput.on('change', alarm);

xInput.on('click', alarm);

xButton.on('click', alarm);

function alarm() {
  return alert('Activated')
}
&#13;
/* For demo it's not required */

[type='text'] {
  width: 5ex;
}
b {
  font-size: 20px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='f1' name='f1'>
  <input type='text'>

  <input type='button' value='BUTTON TYPE'>
  <label><b>⇦</b>Remove this button</label>

  <button>BUTTON TAG</button>
  <label><b>⇦</b>Replace it with this button</label>

</form>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

在一个相当典型的场景中,您的输入旁边有一个按钮,例如快速搜索 您希望在输入更改时触发(即onblur),但也可以在用户单击按钮时触发。

如果用户更改输入然后单击按钮而不更改输入焦点(即没有模糊),则更改事件将触发,因为文本已更改并且单击事件因单击按钮而触发。

一个选项是去抖所需的事件处理程序。

您可以使用插件或简单的setTimeout / clearTimeout,例如:

$('#inp').change(debounceProcess)
$('#btn').click(debounceProcess);

function debounceProcess() {
  if (debounceProcess.timeout != null)
    clearTimeout(debounceProcess.timeout);
  debounceProcess.timeout = setTimeout(triggerProcess, 100)
}

function triggerProcess() {
  console.log('process')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="inp">
<button id="btn">Click</button>