我希望当用户按下某个键时,onkeydown
事件只触发一次函数。如果要再次触发该函数,则必须释放该键并再次按下或长按。
我知道这很简单,但我还是很新手。另外,我希望避免使用jQuery或其他库。
还有一件事,这应该在IE和Firefox中都能正常工作。
我希望当用户按下某个键时,onkeydown
事件只触发一次函数。如果要再次触发该函数,则必须释放该键并再次按下或长按。
我知道这很简单,但我还是很新手。另外,我希望避免使用jQuery或其他库。
还有一件事,这应该在IE和Firefox中都能正常工作。
我很惊讶这没有提到,还有 event.repeat
:
document.addEventListener('keydown', (e) => {
if (e.repeat) return;
console.log(e.key);
});
每次按键时,这个事件只会触发一次,因为event.repeat
在按住键后会变成true
。
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#keyboardevent_sequence
var fired = false;
element.onkeydown = function() {
if(!fired) {
fired = true;
// do something
}
};
element.onkeyup = function() {
fired = false;
};
或者解绑并重新绑定事件处理程序(可能更好):
function keyHandler() {
this.onkeydown = null;
// do something
}
element.onkeydown = keyHandler;
element.onkeyup = function() {
this.onkeydown = keyHandler;
};
您可能还想使用addEventListener
和attachEvent
来绑定事件处理程序。如需更多信息,请查看quirksmode.org - 高级事件注册模型。
有一个可以使用的“once”参数
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
例如:
element.addEventListener('keydown', function(event) {
doSomething()
}, {once: true});
一旦调用它,它就会立即删除。
如果是命名函数,您也可以使用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();
在jsfiddle上有代码示例。
需要注意的是,对于IE浏览器,您需要使用attachEvent
、detachEvent
方法。
attachEvent
。 - Felix Kling给你:
test.onkeydown = function() {
if ( this.className === 'hold' ) { return false; }
this.className = 'hold';
// call your function here
};
test.onkeyup = function() {
this.className = '';
};
JQuery的one会对你有所帮助。
它的作用是将事件处理程序绑定到事件上,当事件发生时,运行事件处理程序并解除绑定,以便在下一个事件中不再触发。
one
本身并没有帮助。你必须重新绑定事件处理程序。 - Felix Kling这是我的解决方案,它只会在目标(例如window
或某个input
字段)上首次按下键时运行您传递的函数。如果用户想再次触发键,则必须释放它并再次按下。
原生 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);
};
};
然后使用它:
const removeListener = onKeyPress((event) => console.log(event.which + ' key pressed'))
removeListener(); // when you want to remove listeners later
React和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]);
};
然后使用它:
import { useKeyPress } from 'wherever';
useKeyPress((event) => console.log(event.which + ' key pressed'))
正如其他答案所述,没有“onkeyfirstdown”或类似的事件可供监听。
最好的解决方案是在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];
});
这样,如果按下多个键,则不会跳过“keyfirstpressed”事件。
(这里发布的许多其他解决方案仅在没有其他键按下时触发)。
document.addEventListener('keydown', ...)
比element.onkeydown
更糟糕吧。为了后代,我删除了之前的评论。 - Sebastian Budka