背景
項(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ī)范。
參考資料
- KeyboardEvent from MDN: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.
- KeyboardEvent in DOM3 Events Specification: https://w3c.github.io/uievents/#interface-keyboardevent.