防止JavaScript keydown事件在按下时被多次处理

时间:2011-05-22 12:34:57

标签: javascript

我有这段代码:

else if (e.keyCode == 32){
      fired = true;

在keyDown函数中(我添加了document.addEventListener代码)。现在它工作正常,并完全按照我的要求去做。但问题出在这里:如果你按住键,它会一直反复地持续激活= true,直到它被释放。我只想要它设置fired = true;一旦,即使关键被按下。

8 个答案:

答案 0 :(得分:17)

    var fired = false;

    element.onkeydown = function() {

        if(!fired) {
            fired = true;
            // do something
        }
    };
  

然后使用onkeyup事件

    element.onkeyup = function() {
     fired = false;
    };

答案 1 :(得分:6)

如果浏览器兼容性不是您主要关注的问题*,您可以尝试访问.repeat的{​​{1}}属性,如下所示:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

通过在处理函数中执行类似的操作:

KeyboardEvent

你可以避免重复击键。

*:在MDN网站上它声明它可以在Firefox中运行,并且我已经在Chrome中成功使用了它,因此两个主流浏览器应该没有问题

答案 2 :(得分:3)

试试这个:)

如果密钥关闭,只需确定keydown是否为真,您就可以确定脚本中的任何其他位置!您还可以在密钥关闭时执行其他脚本,方法是在密钥关闭时将console.log();替换为您想要关闭的任何内容。

请告诉我是否可以改进。

var keydown = false;
window.addEventListener('keydown', function() {
  if (!keydown) {
    keydown = true;
    console.log('key down');
  }
  window.addEventListener('keyup', function() {
    keydown = false;
  });
});

答案 3 :(得分:1)

使用keyup事件。当钥匙被抬起时会被解雇。

答案 4 :(得分:1)

处理此问题的另一种方法(由我的朋友建议):

  1. 请注意每次keydown事件发生时的timeStamp

  2. 计算当前timeStamp(t2)与上一次timeStamp(t1)之间的差异

  3. (a)如果差异小于某个预定阈值,那么它是第二个keydown(意味着我们已经执行了在该事件上发生的代码)。因此,我们可能会选择不再执行代码

    (b)如果差异大于预定阈值,那么它是第一个keydown。因此,我们将执行代码

答案 5 :(得分:1)

上面的解决方案不考虑多次按键(想象一下用户可以同时按下并离开的游戏,但两者都只需要触发一次)。 我需要一个通用的解决方案来禁用所有键的多个keyPress上的键重复:

// create an array with 222 (number of keycodes) values set to true
var keyEnabledArray = Array(222).fill(true);

document.onkeydown = function(e){
    // disable the key until key release
    if(keyEnabledArray[e.keyCode]) {
        keyEnabledArray[e.keyCode] = false;
    }
};

document.onkeyup = function(e){
    // enable the specific key on keyup
    keyEnabledArray[e.keyCode] = true;
}; 

检查以下代码段:



// create an array with 222 true values
var keyEnabledArray = Array(222).fill(true);

document.onkeydown = function(e){
    // disable the key until key release
    if(keyEnabledArray[e.keyCode]) {
        keyEnabledArray[e.keyCode] = false;
        document.getElementById('console').innerHTML += e.keyCode + '<br>';
    }
    
};

document.onkeyup = function(e){
    keyEnabledArray[e.keyCode] = true;
};
&#13;
Press a key:
<div id='console'></div>
&#13;
&#13;
&#13;

答案 6 :(得分:0)

为避免重复发生keydown事件,请在触发后将其阻止,并使用keyup对其进行取消阻止。 您应该避免全局使用变量“ fired”,因此在ES6 +中使用代码块或在旧版JS中使用闭包。

对于ES6:

{ let fired = false;    // code block to exclude 'fired' from global scope
    element.addEventListener('keydown', (e) => {
        // only accept key down when was released
        if(!fired) {
            fired = true;
            // check what key pressed...
            if (e.keyCode === 32) {
                // and do what you need with it
            }
        }
    });

    element.addEventListener('keyup', (e) => {
        fired = false;
    });
}

对于旧版JS,请使用IIFE:

(function(){
    let fired = false;
    element.addEventListener('keydown', function(e) {
        // only accept key down when was released
        if(!fired) {
            fired = true;
            // check what key pressed...
            if (e.keyCode === 32) {
                // and do what you need with it
            }
        }
    });

    element.addEventListener('keyup', function(e) {
        fired = false;
    });
})();

答案 7 :(得分:0)

不同于上述匈牙利的解决方案,如果return falsee.repeat,则我的用例要求我执行以下操作,以有效地禁用文本输入/文本区域上的onChange事件。

function keyDown (e) {
  if(e.repeat) {
    e.preventDefault()
  }

  // do stuff here
}

我的用例的更大上下文(在JSX中):

<textarea 
  ref={formulaInput}
  defaultValue={formulaDefinition.string}
  onDoubleClick={handleLock} 
  onKeyUp={handleUnlock}
  onKeyDown={(e) => {
    if(e.repeat) {
      e.preventDefault()
    }
  }}
  onKeyPress={(e) => {
    if(e.repeat) {
      e.preventDefault()
    }
  }}
  readOnly={!focusLock}
  onChange={handleChange} 
  className={`formula-input ${focusLock ? 'formula-input__locked' : ''}`}
  id='2'
></textarea>