如何在Javascript中检测按键?

109
在互联网上看了很多建议(使用window.onkeypress、使用jQuery等),但几乎每个选项都有反驳的论点。我该如何在Javascript中检测按键操作?

1
我建议只监听按键事件,或者可能是它的某个对应事件(keydown或keyup)。 - Kevin B
1
从这里开始 - http://api.jquery.com/keypress/ - Adil Shaikh
4
jQuery就是JavaScript,唯一的区别在于jQuery是一个库,用来抽象掉跨浏览器的差异,从而使编写跨浏览器代码更加容易(但不一定更高效)。 - David Thomas
我建议使用这个:https://github.com/madrobby/keymaster - SeinopSys
6个回答

131

使用纯JavaScript,最简单的方法是:

document.onkeypress = function (e) {
    e = e || window.event;
    // use e.keyCode
};

但是这样只能为事件绑定一个处理程序。

此外,您可以使用以下方法来潜在地将多个处理程序绑定到同一事件:

addEvent(document, "keypress", function (e) {
    e = e || window.event;
    // use e.keyCode
});

function addEvent(element, eventName, callback) {
    if (element.addEventListener) {
        element.addEventListener(eventName, callback, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + eventName, callback);
    } else {
        element["on" + eventName] = callback;
    }
}

无论哪种情况,keyCode在不同的浏览器中表现不一致,因此还需要进行更多的检查和解决。请注意 e = e || window.event - 这是Internet Explorer的一个普遍问题,在这种情况下,它将事件放在window.event而不是将其传递给回调函数。

参考资料:

使用jQuery:

$(document).on("keypress", function (e) {
    // use e.which
});

参考资料:

除了 jQuery 是一个 "大型" 库之外,jQuery 在处理浏览器之间的差异方面确实非常有帮助,特别是在处理窗口事件方面...这是无法否认的。希望明显的是,我为您提供的 jQuery 代码更加优雅和简短,但仍以一致的方式完成了您想要的功能。您应该能够相信 e (事件) 和 e.which (键码,用于知道按下了哪个键) 是准确的。在普通的 JavaScript 中,要知道这一点有点困难,除非您做 jQuery 库内部所做的一切。

请注意,有一个keydown事件,与keypress不同。您可以在这里了解更多信息:onKeyPress Vs. onKeyUp and onKeyDown

至于建议使用什么,我肯定会建议您学习这个框架并使用 jQuery。同时,我会说您应该学习 JavaScript 的语法、方法、功能以及如何与 DOM 进行交互。一旦您理解了它是如何工作的以及发生了什么,您应该更加舒适地使用 jQuery。对我来说,jQuery 使事情更加一致并更加简洁。最终,它是 JavaScript,并包装了这门语言。

jQuery 非常有用的另一个例子是 AJAX。浏览器在处理 AJAX 请求时不一致,因此 jQuery 将其抽象化,以便您无需担心。

以下是可能有所帮助的内容:


1
如果你想要实现跨浏览器兼容性,你可能也需要涉及到attachEvent()(顺便说一下,这不是我的投票)。 - David Thomas
1
@DavidThomas 我不担心被踩,我更想传达正确的观点。这个答案有改进吗?如果需要,我很乐意添加/更改任何内容。 - Ian
1
看起来很不错,感谢解释!我想我会选择jQuery,我已经更深入地研究了它,如果我学会使用它,这对我也会有好处。 - bobismijnnaam
2
我认为值得注意的是,在我的情况下 keypress 没有起作用,所以我不得不使用 keydown - William Jones
4
那是因为它已被弃用了!我刚刚查看了文档,发现这个惊喜:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/keypress_event#Browser_compatibility。 - Jose A
显示剩余4条评论

56

按键事件(回车键)
点击代码片段内部并按下回车键。

纯 JavaScript

document.addEventListener("keypress", function(event) {
  if (event.keyCode == 13) {
    alert('hi.');
  }
});

香草简写(箭头函数,ES6)

this.addEventListener('keypress', event => {
  if (event.keyCode == 13) {
    alert('hi.')
  }
})

jQuery

$(this).on('keypress', function(event) {
  if (event.keyCode == 13) {
    alert('hi.')
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

jQuery经典版

$(this).keypress(function(event) {
  if (event.keyCode == 13) {
    alert('hi.')
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

jQuery简写(箭头函数,ES6)

$(this).keypress((e) => {
  if (e.keyCode == 13)
    alert('hi.')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

更短的代码(ES6,ECMAScript 2021)

$(this).keypress(e=>
  e.which==13&&alert`☺`
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

由于一些请求,这里提供一份解释:
我重新编写了这个答案,因为随着时间的推移,有些东西已经过时了,所以我进行了更新。只是为了提醒,它不是关于 "keydown",而是关于 "keypress"。因此,一些非字符键,如 "Esc" 不应该像那样工作,但我会解释。
当 document 准备好时,我使用 this 将焦点放在结果内部的窗口范围内,出于简洁起见,但这并不是必要的。 已废弃:
.which.keyCode方法实际上已经被视为废弃,因此我建议使用.code,但我个人仍然使用keyCode,因为性能更快,这对我来说很重要。 jQuery经典版本的.keypress()并非官方废弃,但一些人认为它们不再被推荐使用,而.on('keypress')具有更多功能(动态状态、多个处理程序等)。 在Vanilla版本中,'keypress'事件也已经过时。人们应该优先考虑beforeinputkeydown,以及今天的keyup

性能:
越快越好。这就是为什么我更喜欢 .keyCode,即使它在大多数情况下被认为是过时的。不过这完全取决于你(已提交于2020年)。

性能测试


关于 document.addEventListener("keypress", function(event):好的,但为什么我不能“捕获”[Esc]键? - Apostolos
1
因为[Esc]键应该与“keydown”一起使用。 我之所以这样说是因为它已被弃用......请仔细阅读。最好使用keypress来处理ASCII字符(D,L,%,1,Ä等),并使用keydown来处理非字符键(箭头键,Esc,Alt,Ctrl,Page up / down等)。随着时间的推移,事物可能会发生改变... - Thielicious
谢谢你,@Thielicious。我想我已经回复了。但是我也没有看到我最后一次回复你的消息!至少不在这里,而且我肯定没有删除它!似乎要么是别人删除了,要么是我自己无法看到它们(尽管这听起来很奇怪)!(此外,如果我删除了我的消息,那你怎么会回复它们呢?)无论如何,再次感谢!(希望这能传达过去!) - Apostolos

38

使用 event.key 和现代JS!

不再需要数字代码。你可以直接使用"Enter""ArrowLeft""r"或任何键名,使你的代码更易读。

注意:旧的替代方案(.keyCode.which)已过时。

document.addEventListener("keypress", function onEvent(event) {
    if (event.key === "ArrowLeft") {
        // Move Left
    }
    else if (event.key === "Enter") {
        // Open Menu...
    }
});

Mozilla 文档

支持的浏览器


2
箭头键实际上是“ArrowUp”、“ArrowDown”、“ArrowRight”和“ArrowLeft”。 - Captain Fantastic
1
为什么我无法“捕获”这些箭头键或[Esc]键? - Apostolos
捕获按键:https://dev59.com/4XNA5IYBdhLWcg3wk-6A#46210516 - Gibolt

7

不要过于复杂化。

  document.addEventListener('keydown', logKey);
    function logKey(e) {
      if (`${e.code}` == "ArrowRight") {
        //code here
      }
          if (`${e.code}` == "ArrowLeft") {
        //code here
      }
          if (`${e.code}` == "ArrowDown") {
        //code here
      }
          if (`${e.code}` == "ArrowUp") {
        //code here
      }
    }

恭喜!这个答案应该得到全部的功劳!除了能够“捕捉”箭头键和[Esc]键外,所有早期代码都失败了(至少对我来说),它实际上可以捕捉所有的键盘按键,包括状态键! - Apostolos
还有一件事:我该如何删除这个事件监听器?我尝试使用 document.removeEventListener(),但它不起作用:监听器仍然处于活动状态,即键盘仍然在被监视! - Apostolos
1
虽然这个答案可能不是OP所寻找的,因为它只涉及到keypress(尽管一般来说keypress已经过时了,新的事件如keydown/keyup/beforeinput变得更加方便,而且这个问题已经8年了),但我仍然想补充一下:keydown会在你按住键时持续触发事件,这并不总是好的。因此,可以添加event.repeat = false以防止这种情况的发生。 - Thielicious

6

有几种方法可以处理这个问题;纯JavaScript可以很好地解决:

function code(e) {
    e = e || window.event;
    return(e.keyCode || e.which);
}
window.onload = function(){
    document.onkeypress = function(e){
        var key = code(e);
        // do something with key
    };
};

或者更结构化的处理方式:

或者更加有条理地处理它:

(function(d){
    var modern = (d.addEventListener), event = function(obj, evt, fn){
        if(modern) {
            obj.addEventListener(evt, fn, false);
        } else {
            obj.attachEvent("on" + evt, fn);
        }
    }, code = function(e){
        e = e || window.event;
        return(e.keyCode || e.which);
    }, init = function(){
        event(d, "keypress", function(e){
            var key = code(e);
            // do stuff with key here
        });
    };
    if(modern) {
        d.addEventListener("DOMContentLoaded", init, false);
    } else {
        d.attachEvent("onreadystatechange", function(){
            if(d.readyState === "complete") {
                init();
            }
        });
    }
})(document);

好的,但是为什么我不能“捕获”[Esc]键呢? - Apostolos

0

在编程中,捕获按键事件非常稳定。我以前在多个场合使用过这段代码,并取得了积极的结果。

此链接将显示您按下键时的键码。 查找键码

$("#your_input_id").keydown(function(event) {
if(event.keyCode == 189) {
    alert('Dexter');
}
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接