Javascript onkeydown 事件只触发一次?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5353254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:48:33  来源:igfitidea点击:

Javascript onkeydown event fire only once?

javascriptdom-events

提问by WindowsMaker

I want to have a onkeydownevent fire a function only once. for that function to fire again, the user has to release the key and press/hold again. I know its fairly simple but I'm new at JS. Also I prefer to avoid using jQuery or other libs. One more thing, this should work for both ie and firefox.

我想让一个onkeydown事件只触发一次函数。要再次触发该功能,用户必须松开按键并再次按住/按住。我知道它相当简单,但我是 JS 的新手。另外我更喜欢避免使用 jQuery 或其他库。还有一件事,这应该适用于 ie 和 firefox。

回答by Felix Kling

You could set a flag:

你可以设置一个标志:

var fired = false;

element.onkeydown = function() {
    if(!fired) {
        fired = true;
        // do something
    }
};

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

Or unbind and rebind the event handler (might be better):

或者取消绑定并重新绑定事件处理程序(可能更好):

function keyHandler() {
     this.onkeydown = null;
     // do something
}

element.onkeydown = keyHandler;

element.onkeyup = function() {
    this.onkeydown = keyHandler;
};

More information about "traditional" event handling.

有关“传统”事件处理的更多信息。

You might also want to use addEventListenerand attachEventto bind the event handlers. For more information about that, have a look at quirksmode.org - Advanced event registration models.

您可能还想使用addEventListenerattachEvent绑定事件处理程序。有关更多信息,请查看quirksmode.org - 高级事件注册模型

回答by ?ime Vidas

Here you go:

干得好:

test.onkeydown = function() {
    if ( this.className === 'hold' ) { return false; }
    this.className = 'hold';

    // call your function here
};

test.onkeyup = function() {
    this.className = '';
};

Live demo:http://jsfiddle.net/simevidas/xAReL/2/

现场演示:http : //jsfiddle.net/simevidas/xAReL/2/

回答by Mark Coleman

Here is a method that uses addEventListenerand removeEventListener

这是一种使用addEventListener和的方法removeEventListener

var textBox = document.getElementById("textBox");
function oneKeyDown(){
    $("body").append("<h1>KeyDown<h1>"); //just to show the keypress
    textBox.removeEventListener('keydown', oneKeyDown, false);
}
function bindKeyDown(){
  textBox.addEventListener('keydown', oneKeyDown, false);
}
textBox.addEventListener('keyup', bindKeyDown, false)   
bindKeyDown();

Code example on jsfiddle.

jsfiddle上的代码示例。

One note, for IE you will need to use attachEvent, detachEvent.

请注意,对于 IE,您需要使用attachEvent,detachEvent

回答by josh

as stated in the other answers, there is no 'onkeyfirstdown' or similar event to listen for.

正如其他答案中所述,没有“onkeyfirstdown”或类似的事件可以监听。

the best solution is to keep track of which keys are already down in a js-object:

最好的解决方案是跟踪 js 对象中哪些键已经关闭:

var keysdown = {};

element.addEventListener('keydown', function(evt) {
  if(!(evt.key in keysdown)) {
    keysdown[evt.key] = true;
    // key first pressed
  }
});

element.addEventListener('keyup', function(evt) {
  delete keysdown[evt.key];
});

this way, you will not be skipping 'keyfirstpressed' events if more than one key is held down.

这样,如果按住多个键,您将不会跳过“keyfirstpressed”事件。

(many of the other solutions posted here will only fire when no other keys are down).

(此处发布的许多其他解决方案仅在没有其他键按下时才会触发)。

回答by Alistair R

There's a "once" parameter you can use

您可以使用“一次”参数

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Eg:

例如:

element.addEventListener('keyup', function(event) {  
    doSomething()
}, {once: true});

It'll remove it as soon as it's been called.

它会在调用后立即将其删除。

Alternatively you can use removeEventListenerif it's a named function

或者,removeEventListener如果它是命名函数,您可以使用

回答by V. Rubinetti

Here is my solution that will only run the function you pass it when a key is FIRST pressed on the target (eg windowor some inputfield). If the user wants to trigger a key again, they'll have to release it and press it again.

这是我的解决方案,它只会在目标(例如window或某个input字段)上第一次按下键时运行您传递给它的函数。如果用户想再次触发一个键,他们必须松开它并再次按下它。



Vanilla JS

香草JS

const onKeyPress = (func, target = window) => {
  // persistent "store" to track what keys are being pressed
  let pressed = {};

  // whenever a keydown event is fired ontarget element
  const onKeyDown = (event) => {
    // if key isn't already pressed, run func
    if (!pressed[event.which])
      func(event);

    // add key to store
    pressed = { ...pressed, [event.which]: true };
  };

  // whenever a keyup event is fired on the window element
  const onKeyUp = (event) => {
    const { [event.which]: id, ...rest } = pressed;
    // remove key from store
    pressed = rest;
  };

  // add listeners
  target.addEventListener('keydown', onKeyDown);
  window.addEventListener('keyup', onKeyUp);

  // return a function that can be called to remove listeners
  return () => {
    target.removeEventListener('keydown', onKeyDown);
    window.removeEventListener('keyup', onKeyUp);
  };
};

And then to use it:

然后使用它:

const removeListener = onKeyPress((event) => console.log(event.which + ' key pressed'))

removeListener(); // when you want to remove listeners later


React and React Hooks

反应和反应钩子

import { useState } from 'react';
import { useEffect } from 'react';
import { useCallback } from 'react';

export const useKeyPress = (func, target = window) => {
  // persistent "store" to track what keys are being pressed
  const [pressed, setPressed] = useState({});

  // whenever a keydown event is fired ontarget element
  const onKeyDown = useCallback(
    (event) => {
      // if key isn't already pressed, run func
      if (!pressed[event.which])
        func(event);

      // add key to store
      setPressed({ ...pressed, [event.which]: true });
    },
    [func, pressed]
  );

  // whenever a keyup event is fired on the window element
  const onKeyUp = useCallback((event) => {
    // remove key from store
    const { [event.which]: id, ...rest } = pressed;
    setPressed(rest);
  }, [pressed]);

  useEffect(() => {
    // add listeners when component mounts/changes
    target.addEventListener('keydown', onKeyDown);
    window.addEventListener('keyup', onKeyUp);

    // cleanup/remove listeners when component unmounts/changes
    return () => {
      target.removeEventListener('keydown', onKeyDown);
      window.removeEventListener('keyup', onKeyUp);
    };
  }, [target, onKeyDown, onKeyUp]);
};

And then to use it:

然后使用它:

import { useKeyPress } from 'wherever';

useKeyPress((event) => console.log(event.which + ' key pressed'))

回答by simplyharsh

JQuery's onewill help you.

JQuery 的一个会帮助你。

What it does is, bind the eventHandler to event, and when event occurs, it runs the eventHandler and unbinds it, so that its not fired at next event.

它的作用是将 eventHandler 绑定到事件,当事件发生时,它运行 eventHandler 并解除绑定,这样它就不会在下一个事件中被触发。