草庐IT

javascript - 跨浏览器跨操作系统获取 keyCode/字符按下 onkeydown 事件的方法

coder 2024-07-16 原文

例如,如果我有这个:

<input type='text' onkeydown='doSomething()' />

<script>
  function doSomething() {
    // ?
  }
</script>

我需要以跨浏览器/操作系统的方式按下 keyCode/character .. 怎么做?我在 6 年前尝试过这个,我记得那个时候,这并不容易,有时我必须通过事件或其他东西才能让它在歌剧或 IE cmiiw 上工作

最佳答案

你已经接近了,但你的代码的问题是你正在执行 doSomething()回应keyDown事件...让我们仔细看看——你正在执行 doSomething没有传递任何参数。即使您确实传递了参数,您也没有命名/接受参数。

对您的代码进行一些快速调整,一切就绪:

// Notice an `event` argument, containing the important data
function doSomething(event) {
  console.log('****** doSomething');
  console.log('event.keyCode: ', event.keyCode);
  console.log('event.which: ', event.which);
  console.log('event.key: ', event.key);
  console.log('event.code: ', event.code);
}
<!-- Notice: We pass the key `event` object into doSomething -->
<input type='text' onkeydown='doSomething(event)' placeholder="Type here..." />


如何确定按下了什么键

我对此也感到困惑,但让我们回顾一下这些选项。为 1995 年的浏览器差异做好准备!

首先,请记住,虽然最终目标可能是确定按下了哪个键,但不同的方法需要不同的步骤才能实现。事件可以是“系统和实现相关的数字代码”、Unicode 字符值、Ascii 值或实际键名(“ArrowUp”)。
event.key ( TL;DR:尝试使用这个 )

根据MDN KeyboardEvent.key Documentation , event.key如果您正在寻找不被弃用的“面向 future ”的方式,这是推荐的方式。文档正在大量修改中,因此 MDN 上的细节很少。

看着caniuse.com support table对于 event.key ,在 IE11 以下或 Safari 上根本不支持(截至 2017 年 1 月)。这可能已经是一个交易破坏者,所以让我们继续寻找。
event.keyCode
我一直用event.keyCode , 其中 MDN says is now deprecated并附带此警告:

You should avoid using this if possible; it's been deprecated for some time. Instead, you should use KeyboardEvent.code, if it's implemented. Unfortunately, some browsers still don't have it, so you'll have to be careful to make sure you use one which is supported on all target browsers. Google Chrome and Safari have implemented KeyboardEvent.keyIdentifier, which was defined in a draft specification but not the final spec.



好吧,很公平——浏览器之间有足够的差异,keydown 之间有细微的差异。和 keypress事件( not the same thing! )使其不再值得使用。 RIP keyCode ,这是真的!
event.which
来自 MDN docs :

The numeric code for a particular key pressed, depending on whether an alphanumeric or non-alphanumeric key was pressed. Please see KeyboardEvent.charCode** and KeyboardEvent.keyCode for more details.



另一个正在弃用的——“这个特性已经从 Web 标准中删除。虽然一些浏览器可能仍然支持它,但它正在被删除。”

好吧,好吧keyCode我们已经知道它也被弃用了,那么 charCode 是什么?关于?
event.charCode
这将返回 keypress 的 Unicode 字符代码事件...和we get another warning from MDN :

Do not use this property anymore, it is deprecated. Use KeyboardEvent.key instead.



开始在这里追逐我们自己的尾部,KeyboardEvent.key是面向 future 的方法,但尚未得到充分支持...它还返回 0一直为keydown事件,你必须听keypress事件才有值(value)。
event.code
最后一个选项似乎很有希望... event.code docs from MDN :

represents a physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value which isn't altered by keyboard layout or the state of the modifier keys.



这很方便,因为我们得到了像 ShiftRight 这样的东西。与 ShiftLeft 相比,对于游戏开发和非常具体的交互很有用。所有代码选项的文档底部都有一个很棒的图表。

收获:not very good support yet . IE、iOS Safari、Android 或 Opera 上没有任何内容。

那么......我应该使用什么?

TBH 我认为没有一刀切的解决方案。目前的情况似乎需要某种程度的 polyfill,或者至少支持旧的 event.keyCodeevent.which属性作为 where event.key 的后备和 event.code不能使用。

对于生产项目,我们只需要考虑浏览器和设备支持要求,然后从那里开始。

Shift/Ctrl/Command/Windows/等

有一些额外的属性可以检查您是否关心与原始键组合按下的其他键:
  • event.altKey
  • event.ctrlKey
  • event.metaKey
  • event.shiftKey

  • 方便的工具:keycode.info
    http://keycode.info/ 是一个非常有用的工具,可以快速找出您需要围绕哪些 keyCode 编写逻辑。 (由 v.cool Wes Bos 创建)

    关于javascript - 跨浏览器跨操作系统获取 keyCode/字符按下 onkeydown 事件的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15108670/

    有关javascript - 跨浏览器跨操作系统获取 keyCode/字符按下 onkeydown 事件的方法的更多相关文章

    1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    2. Ruby 解析字符串 - 2

      我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

    3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

      我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

    4. ruby-on-rails - unicode 字符串的长度 - 2

      在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

    5. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    6. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

      大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

    7. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

      我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

    8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

      我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

    9. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

      我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

    10. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

      在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

    随机推荐