简体   繁体   English

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

[英]Prevent JavaScript keydown event from being handled multiple times while held down

I have this code:我有这个代码:

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

In a keyDown function (I have added the document.addEventListener code).在 keyDown 函数中(我添加了 document.addEventListener 代码)。 Now it works just fine, and does exactly what I want it to do.现在它工作得很好,并且完全符合我的要求。 But here's the problem: if you hold down the key, it keeps making fired = true over and over again continuously until it is released.但问题是:如果你按住这个键,它会一遍又一遍地不断地使 fire = true 直到它被释放。 I just want it to set fired = true;我只是想让它设置 fire = true; once, even if the key is held down.一次,即使按键被按下。

Edit: It is now fully supported in every browser except for Internet Explorer编辑:现在除了 Internet Explorer 之外的所有浏览器都完全支持它

If browser compatibility is not your main concern* , you could try accessing the .repeat property of the KeyboardEvent , as documented here:如果浏览器兼容性不是您的主要关注点* ,您可以尝试访问KeyboardEvent.repeat属性,如下所述:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

By doing something like this in your handler function:通过在你的处理函数中做这样的事情:

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

  // do stuff here
}

you could avoid the repeated keystrokes.您可以避免重复击键。


*: on the MDN site it states that it works in Firefox, and I have successfully used it in Chrome, so the two major browsers should have no problem with it *:在MDN站点上说它可以在Firefox中运行,我在Chrome中成功使用了它,所以两大浏览器应该没有问题

    var fired = false;

    element.onkeydown = function() {

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

Then Use onkeyup event然后使用 onkeyup 事件

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

Try this :)尝试这个 :)

You can determine anywhere else in your script if a key is down by simply determining if keydown is true!您可以通过简单地确定keydown是否为真来确定脚本中的任何其他地方是否按下了键! You can also execute additional script when a key is down by replacing the console.log();您还可以通过替换console.log();在某个键关闭时执行其他脚本console.log(); with whatever you want to be down when a key is down.当一个键被关闭时,无论你想关闭什么。

Please tell me if this can be improved.请告诉我这是否可以改进。

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

Another approach to handle this (suggested by my friend):处理此问题的另一种方法(由我的朋友建议):

  1. Note the timeStamp when everytime the keydown event happens请注意每次 keydown 事件发生时的时间戳

  2. Calculate the difference between current timeStamp (t2) and the previous timeStamp (t1)计算当前时间戳(t2)和前一个时间戳(t1)之间的差异

  3. (a) If the difference is less than some predetermined threshold, then it is the second keydown (means we have already executed the code to happen on that event). (a) 如果差异小于某个预先确定的阈值,那么它是第二次 keydown(意味着我们已经执行了在该事件上发生的代码)。 Hence, we may choose not to execute the code again因此,我们可能会选择不再执行代码

    (b) If the difference is greater than the predetermined threshold, then it is the first keydown. (b) 如果差值大于预定阈值,则为第一个 keydown。 Hence, we would execute the code因此,我们将执行代码

Solutions above dont take in account multiple key presses (imagine a game where the user can presse up and left at the same time but both need to be triggered just once).上面的解决方案不考虑多次按键(想象一个游戏,用户可以同时按下向上和向左,但都只需要触发一次)。 I needed a universal solution for disabling key repeat on multiple keyPress for ALL keys:我需要一个通用解决方案来禁用所有键的多个 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;
}; 

Check the snippet below:检查下面的片段:

 // 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; };
 Press a key: <div id='console'></div>

To avoid repeated keydown event, block it after firing and unblock it with keyup .为避免重复keydown事件,请在触发后阻止它并使用keyup解除阻止。 You should avoid variable 'fired' being global, so use code block with ES6+ or closure in older version of JS.你应该避免变量“fired”是全局的,所以在旧版本的 JS 中使用带有 ES6+ 的代码块或闭包。

For ES6:对于 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;
    });
}

For older version of JS use IIFE:对于旧版本的 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;
    });
})();

Use keyup event.使用keyup事件。 It is fired when they key is lifted.当他们的钥匙被解除时它被触发。

Unlike the solution above from Hungary where you return false if e.repeat is true, my use case required me to do the following to effectively disable the onChange event on a text input/textarea.与上面来自匈牙利的解决方案不同,如果e.repeat为 true,则return false ,我的用例要求我执行以下操作以有效禁用文本输入/文本区域上的 onChange 事件。

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

  // do stuff here
}

Larger context of my use case (in JSX):我的用例的更大上下文(在 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 按住多个键时未触发JavaScript KeyDown事件 - JavaScript KeyDown event not triggered when multiple keys are held down jQuery使用keydown / keyup / keypress事件仅触发一次,而不是按住键时触发多次 - jQuery using keydown/keyup/keypress event to fire only one time instead of multiple times when key held down 如何在不捕获keydown事件的情况下查看修改键是否被按下? - How to see if a modifier key is being held down without catching the keydown event? 单击事件多次触发并按住 Enter 键 - Click event fires multiple times with enter key being held 防止keydown事件javascript - Prevent keydown event javascript Javascript:限制按下按键事件监听器在按下时可以多快调用一次函数 - Javascript: Limit how quickly a keydown event listener can call a function when held down 防止按钮在按住时连续触发 - Prevent button from continuously firing while being held 如果触发了 keydown 事件,则防止模态关闭 - Prevent modal from closing down if there is a keydown event that has been triggered 防止退格和删除被香草JS中的输入事件“处理” - Prevent Backspace and Delete from being "handled" by input event in vanilla JS 当按住输入键时,防止按键方法被多次调用 - Prevent keypress method to be called multiple times when enter key held down
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM