KeyboardEvent和快捷鍵

背景

項(xiàng)目中需要對(duì)網(wǎng)頁的 UI 操作設(shè)置快捷鍵,但是我們的開發(fā)機(jī)是 Mac菠镇,用戶使用的是 Windows椎瘟。所以開發(fā)起來遇到一些小小的坑。現(xiàn)在我們來梳理下這些知識(shí)點(diǎn)愈涩。

基礎(chǔ)知識(shí)

網(wǎng)頁上要設(shè)置快捷鍵最基礎(chǔ)的做法一般是監(jiān)聽 keydown 事件望抽,然后通過監(jiān)聽函數(shù)參數(shù)獲取一些按鍵相關(guān)的屬性來判斷用戶按了哪些按鍵:

  document.addEventListener( 'keydown', function( event ){
    let key = event.key;
    if ( key === 'Enter' ) {
      console.log( '你按下的是回車鍵~' );
    }
  } );

上面的代碼只是做一個(gè)示例加矛,按鍵相關(guān)的屬性有很多個(gè),這些屬性定義在 KeyboardEvent 這個(gè)接口中煤篙。keydown 事件監(jiān)聽函數(shù)接受的第一個(gè)參數(shù) event 就實(shí)現(xiàn)了這個(gè)接口(event不僅僅實(shí)現(xiàn)了 KeyboardEvent 還實(shí)現(xiàn)了其他接口噢)斟览。KeyboardEvent 這個(gè)接口是在 W3C 的 DOM 規(guī)范里面定義的,現(xiàn)在最新發(fā)布的規(guī)范版本是 DOM4舰蟆。不過呢趣惠,KeyboardEvent 在 DOM4 中并沒有什么更新,文檔直接把其定義指向了 DOM3 中的 KeyboardEvent 接口定義身害。所以接下來味悄,讓我們看下規(guī)范中是如何定義鍵盤事件的。

KeyboardEvent

先介紹下我們常用的一些屬性(規(guī)范地址):

  • KeyboardEvent.key
  • KeyboardEvent.code
  • KeyboardEvent.ctrlKey
  • KeyboardEvent.shiftKey
  • KeyboardEvent.altKey
  • KeyboardEvent.metaKey

KeyboardEvent.ctrlKey | shiftKey | altKey | metaKey 比較簡(jiǎn)單塌鸯,表示當(dāng)你按下鍵盤的時(shí)候侍瑟,Ctrl | Shift | Alt | meta 按鍵是否已經(jīng)被按下。如果已經(jīng)被按下這些值就是 true丙猬,通常我們要運(yùn)用組合鍵的判斷會(huì)用到(譬如:Alt + a)涨颜。大家看到 meta 會(huì)疑惑這個(gè)是哪個(gè)鍵?在 Mac 平臺(tái)上指的是 command 鍵(?)茧球,而在 Windows 平臺(tái)指的是 windows 鍵(?)庭瑰。但是不是所有 Windows 電腦鍵盤都有 ? 這個(gè)鍵的。接下來我們介紹下最重要的兩個(gè)屬性 key 和 code抢埋。

KeyboardEvent.key

如果你按下的按鈕所代表的是一個(gè)可打印的字符(printed representation)弹灭,那么這個(gè) key 的值就是這個(gè)字符(譬如:a、Enter揪垄、Shift穷吮、CapsLock、Backspace)饥努。如果是一些特殊字符呢捡鱼,這個(gè)值就可能是 Unidentified。你要問哪些鍵是特殊字符酷愧,這個(gè)驾诈。。溶浴。倫家標(biāo)準(zhǔn)里面說了應(yīng)鍵盤而異翘鸭。這里說的是單獨(dú)按一個(gè)按鍵的場(chǎng)景,組合鍵又不同了戳葵,key 出什么值是有一套簡(jiǎn)單的算法的:

key holds the key value of the key pressed. If the value is has a printed representation, it MUST be a non-empty Unicode character string, conforming to the algorithm for determining the key value defined in this specification.

這里我只介紹最基本的用法,不詳述算法汉匙。

KeyboardEvent.code

這個(gè)值比較詭異拱烁,它表示你按了鍵盤上的哪個(gè)按鍵生蚁。你按 a,code 的值是 KeyA戏自,你按左邊的 Shift邦投,code 的值是 ShiftLeft。什么意思呢擅笔?就是他表示你按的按鍵在鍵盤的哪個(gè)位置志衣。這里就有趣了,因?yàn)椴煌Z言的鍵盤同一個(gè)鍵代表的字符可能不同猛们,但是位置是相同的念脯。打個(gè)比方:KeyQ 代表的是我們普通鍵盤q按鍵。但是呢 Dvorak 鍵盤q這個(gè)位置的按鈕代表的不是 q弯淘,而是'绿店。所以如果你按同一個(gè)按鈕,key 的值可能不同庐橙,code 的值會(huì)相同假勿。

有了上述的幾個(gè)值一般的單個(gè)按鍵和組合鍵都能檢測(cè)到了,不過按照 web 標(biāo)準(zhǔn)的尿性你可能會(huì)猜到态鳖,那兼容性問題呢转培?查下兼容表。浆竭。浸须。key 和 code 兼容性堪憂啊,都是瀏覽器高級(jí)版本支持或者根本不支持兆蕉。那么怎么辦羽戒?

非標(biāo)準(zhǔn)屬性

KeyboardEvent 接口標(biāo)準(zhǔn)經(jīng)歷了許多草稿版本,首先在 DOM2 下由于沒有協(xié)商一致虎韵,它被丟棄易稠; DOM3 重新加入。這導(dǎo)致了在早期的 DOM2 版本中非標(biāo)準(zhǔn)的實(shí)現(xiàn)。

  • KeyboardEvent.char:如果是 printed 的字符慌闭,則值是這個(gè)字符奔脐,如果是按鍵沒有對(duì)應(yīng)的 printed 字符,值為空亡电。(如果該按鍵用作插入多個(gè)字符的宏, 則此屬性的值是整個(gè)字符串, 而不僅僅是第一個(gè)字符。)
  • KeyboardEvent.charCode:是按鍵字符對(duì)應(yīng)的 Unicode 編碼的數(shù)字硅瞧。(對(duì)于其 char 屬性包含多個(gè)字符的按鍵是該屬性中第一個(gè)字符的 Unicode 值份乒。)
  • KeyboardEvent.keyCode:返回一個(gè)代表你所按按鍵的數(shù)字,這個(gè)數(shù)字是和系統(tǒng)實(shí)現(xiàn)相關(guān)。
  • KeyboardEvent.which:通常和 keyCode 是一致的或辖。

DOM3 規(guī)范中說這些過期的屬性會(huì)因平臺(tái)瘾英,鍵盤語言,鍵盤布局等等眾多因素而導(dǎo)致其取值不統(tǒng)一颂暇。

兼容性

如果你要在不同的瀏覽器甚至不同的平臺(tái)使用一套快捷鍵缺谴,你嘗試上述所有說到的屬性,你會(huì)發(fā)現(xiàn)表現(xiàn)幾乎都不一致耳鸯。有的情況是相同按鈕[組合]對(duì)應(yīng)同一個(gè)屬性取出的值不同湿蛔。譬如 Alt + a,當(dāng)你在 a 按下去的時(shí)候去獲取 KeyboardEvent.key 的值县爬,Windows 平臺(tái)得到的是a阳啥,而 Mac 平臺(tái)下得到的是?。有的情況是上述 KeyboardEvent 中很多屬性都不支持捌省,你連挑的機(jī)會(huì)都沒有苫纤,譬如老版本的 IE 幾乎只支持 KeyboardEvent.keyCode 這一個(gè)屬性。

經(jīng)過大量的測(cè)試纲缓,如果你需要一個(gè)大路化通用的解決方案卷拘,只能使用 KeyboardEvent.keyCode 來做統(tǒng)一的判斷。當(dāng)然如果這不能滿足你的要求祝高,那么你可以通過 userAgent 來判斷不同平臺(tái)栗弟,針對(duì)不同平臺(tái)采取不同的快捷鍵策略。以上就是對(duì)這個(gè)知識(shí)點(diǎn)的簡(jiǎn)單梳理工闺,如果想要更深入的如了解鍵盤事件的模型乍赫,請(qǐng)參考下方附上的規(guī)范。

參考資料

  1. KeyboardEvent from MDN: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.
  2. KeyboardEvent in DOM3 Events Specification: https://w3c.github.io/uievents/#interface-keyboardevent.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陆蟆,一起剝皮案震驚了整個(gè)濱河市雷厂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叠殷,老刑警劉巖改鲫,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異林束,居然都是意外死亡像棘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門壶冒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缕题,“玉大人,你說我怎么就攤上這事胖腾⊙塘悖” “怎么了瘪松?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)瓶摆。 經(jīng)常有香客問我凉逛,道長(zhǎng),這世上最難降的妖魔是什么群井? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮毫胜,結(jié)果婚禮上书斜,老公的妹妹穿的比我還像新娘。我一直安慰自己酵使,他們只是感情好荐吉,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著口渔,像睡著了一般样屠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缺脉,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天痪欲,我揣著相機(jī)與錄音,去河邊找鬼攻礼。 笑死业踢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的礁扮。 我是一名探鬼主播知举,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼太伊!你這毒婦竟也來了雇锡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤僚焦,失蹤者是張志新(化名)和其女友劉穎锰提,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叠赐,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡欲账,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芭概。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赛不。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖罢洲,靈堂內(nèi)的尸體忽然破棺而出踢故,到底是詐尸還是另有隱情文黎,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布殿较,位于F島的核電站耸峭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淋纲。R本人自食惡果不足惜劳闹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洽瞬。 院中可真熱鬧本涕,春花似錦、人聲如沸伙窃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽为障。三九已至晦闰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鳍怨,已是汗流浹背呻右。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留京景,地道東北人窿冯。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像确徙,于是被迫代替她去往敵國和親醒串。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 例子: //這條命令相當(dāng)于按了設(shè)備的Backkey鍵 adb shell input keyevent 4 //可...
    井望閱讀 14,229評(píng)論 0 5
  • 手機(jī)端配置tcp方式連接 su setprop service.adb.tcp.port 5555 stop ad...
    yoyo鹿鳴閱讀 5,675評(píng)論 0 4
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理鄙皇,服務(wù)發(fā)現(xiàn)芜赌,斷路器,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程伴逸,因...
    小菜c閱讀 6,450評(píng)論 0 17
  • error code(錯(cuò)誤代碼)=0是操作成功完成缠沈。error code(錯(cuò)誤代碼)=1是功能錯(cuò)誤。error c...
    Heikki_閱讀 3,390評(píng)論 1 9