按住“ enter”键时如何防止触发按钮事件?

时间:2018-09-30 09:16:17

标签: javascript html

案例受到打击:

如果您单击按钮,然后按住“ enter”键不放,则按钮的click事件将不断触发。

document.querySelector('button').addEventListener('click', function (e) {
  console.log(1);
})
<button>press Enter</button>

没有jQuery,没有表单,没有输入。我想知道这是如何工作的以及如何防止它...

谢谢你。

4 个答案:

答案 0 :(得分:2)

之所以发生这种情况,是因为按下按钮上的Enter会触发其单击事件,并且当您按住某个键时,会重复出现重复键并不断重复“键入”该键。

如果要在触发一次事件后的一段时间内忽略该事件,可以将代码添加到处理程序中以执行此操作:

var IGNORE_TIME = 1000; // One second
var lastClick = null;
document.querySelector('button').addEventListener('click', function (e) {
  var now = Date.now();
  if (!lastClick || now - lastClick > IGNORE_TIME) {
    lastClick = now;
    console.log(1);
  }
});
<button>press Enter</button>

如果您从不从不按下按钮上的Enter来“单击”它(我不建议这样做,对于依靠键盘使用的残障人士来说可能会很困难),您可以防止按钮上的keydown事件:

document.querySelector('button').addEventListener('click', function (e) {
  console.log(1);
});
document.querySelector('button').addEventListener('keydown', function (e) {
  var key = e.keyCode || e.charCode;
  if (key == 13) {
    e.stopPropagation();
    e.preventDefault();
  }
});
<button>press Enter</button>

另请参见vlaz's answer,它仅在按键重复时才阻止按键,这似乎是一个很好的折衷方案。

答案 1 :(得分:1)

这是由于单击按钮时出现的。按钮保持焦点状态

答案 2 :(得分:1)

修订后的答案::按住某个键时,您希望获得的事件顺序为keydown-> keypress-> keydown- > keypress->(...同样的两个事件重复出现...)-> keyup。知道了这一点,您就可以跟踪在keydown中按下的内容,并知道它最终以keyup结尾。

document.querySelector('button').addEventListener('click', function (e) {
  console.log(1);
});

var keysCurrentlyPressed = {};

document.querySelector('button').addEventListener('keydown', function (e) {
  var key = e.keyCode || e.charCode;
  if (keysCurrentlyPressed[key]) {
    e.stopPropagation();
    e.preventDefault();
  } else { //this is the first time the key is pressed, add an entry for this key
    keysCurrentlyPressed[key] = true;
  }
});

document.querySelector('button').addEventListener('keyup', function (e) {
  var key = e.keyCode || e.charCode;
  delete keysCurrentlyPressed[key]; //note that the key isn't pressed any more
});
<button>press Enter</button>

这将在任何符合DOM Level 3的环境下运行,因此适用于所有主流浏览器。但是,according to MDN在某些较旧的环境中会将按下的键视为重复按下该键,每次发送keydown-> keypress-> keyup。在这种情况下,您可以使用T.J. Crowder's solution which uses a timeout period

如果使用ES6,则可以将按下的键存储在a Set中,并且可以将整个内容包装在一个封闭的容器中,以防止这些键可用于可能不需要它们的其他代码。

document.querySelector('button').addEventListener('click', function (e) {
  console.log(1);
});

(function() {
  const keysCurrentlyPressed = new Set();

  document.querySelector('button').addEventListener('keydown', e => {
    const key = e.keyCode || e.charCode;
    if (keysCurrentlyPressed.has(key)) {
      e.stopPropagation();
      e.preventDefault();
    } else {
      keysCurrentlyPressed.add(key);
    }
  });

  document.querySelector('button').addEventListener('keyup', e => keysCurrentlyPressed.delete(e.keyCode || e.charCode));

})()
<button>press Enter</button>

原始答案:您可以通过查看Event.repeat属性来防止按下键。但是,Edge或Internet Explorer不支持repeat属性,因此只能在Chrome,Firefox和Safari上使用。

document.querySelector('button').addEventListener('click', function (e) {
  console.log(1);
});

document.querySelector('button').addEventListener('keydown', function (e) {
  if (e.repeat) { //don't do anything if a key is held down.
    e.stopPropagation();
    e.preventDefault();
  }
});
<button>press Enter</button>

如果您为按钮计时并按住Enter键甚至是空格键,则不会重复发生事件。

值得注意的是-您需要添加键盘事件(keydownkeypresskeyup)的侦听器才能使用repeat属性。 click是一个没有repeat的鼠标事件,因为它没有意义。

答案 3 :(得分:0)

由于按钮具有焦点,因此将每个事件(按Enter键)定向到该按钮并执行。为防止它多次发生,您可以使用blur()除去焦点。然后,它只执行一次,直到用户再次将焦点放在按钮上。

document.querySelector('button').addEventListener('click', 
  function (e) {
    console.log(1);
    this.blur();
})