.keyCode vs. .which

228

Myślałem, że odpowiedź na to pytanie znajdzie się gdzieś na Stack Overflow, ale nie mogę tego znaleźć.

Jeśli oczekuję zdarzenia naciśnięcia klawisza, czy powinienem używać .keyCodelub .whichustalić, czy naciśnięto klawisz Enter?

Zawsze robiłem coś takiego:

$("#someid").keypress(function(e) {
  if (e.keyCode === 13) {
    e.preventDefault();
    // do something
  }
});

Ale widzę przykłady, które używają .whichzamiast .keyCode. Co za różnica? Czy jedno jest bardziej przyjazne dla różnych przeglądarek niż drugie?

ScottE
źródło

Odpowiedzi:

209

Uwaga: Odpowiedź poniżej została napisana w roku 2010. Tutaj wiele lat później, zarówno keyCodei whichsą przestarzałe na rzecz key(dla klucza logicznego) oraz code(w przypadku fizycznego umieszczenia klucza). Ale zauważ, że IE nie obsługuje code, a jego obsługa keyoparta jest na starszej wersji specyfikacji, więc nie jest całkiem poprawna. Gdy piszę to, obecny Edge oparty na EdgeHTML i Chakra też nie obsługuje code, ale Microsoft wprowadza na Blink - i V8 zamiennik Edge'a, który prawdopodobnie tak / będzie.


Niektóre przeglądarki używają keyCode, inne używają which.

Jeśli używasz jQuery, możesz niezawodnie używać, whichponieważ jQuery standaryzuje rzeczy ; Więcej tutaj.

Jeśli nie używasz jQuery, możesz to zrobić:

var key = 'which' in e ? e.which : e.keyCode;

Lub alternatywnie:

var key = e.which || e.keyCode || 0;

... która radzi sobie z taką e.whichewentualnością 0(przywracając ją 0na końcu za pomocą niezwykle potężnego ||operatora JavaScript ).

TJ Crowder
źródło
2
Dzięki TJ Gdzie znajdę odniesienie do tego? Nie żebym ci nie wierzył, jestem po prostu ciekawy! ... Widzę, że właśnie to dodałeś, dzięki. Tak więc, nawet dla tych, którzy nie używają jquery, Który lepszy wybór?
ScottE
7
@ScottE: Jeśli nie używasz jQuery, musisz poradzić sobie z tym osobiście. Zwykle robię to w ten sposób, var key = event.which || event.keyCode;który będzie używany, event.whichjeśli jest zdefiniowany, a nie falsey, lub event.keyCodejeśli whichjest niezdefiniowany lub falsey. Technicznie prawdopodobnie powinienem to zrobić, var key = typeof event.which === "undefined" ? event.keyCode : event.which;ale jeśli tak event.whichjest 0(czy to możliwe 0?), Raczej nie dbam o rzeczy, które robię.
TJ Crowder,
2
@ScottE, tutaj jest podstawowe odniesienie: quirksmode.org/js/keys.html (nie obejmuje which, co, jak sądzę, jest zapewnione tylko przez jQuery, ale nie jestem w 100% pewien, ale powinien zacząć od zobaczenia różnice w przeglądarkach)
Mottie
1
@fudgey: whichjest przewidziany keypressprzez wszystkie przeglądarki oprócz IE. Tryb quirksmode nie jest tutaj autorytatywny. Jako odniesienie, link opublikowany przez @TJ Crowder jest znacznie lepszy: unixpapa.com/js/key.html .
Tim Down
5
@TJ Crowder: Tak, właściwość wydarzenia whichmoże wynosić zero, co może mieć duże znaczenie dla większości aplikacji. Na przykład klucze niedrukowalne w przeglądarce Firefox mają whichwłaściwość zero i taką samą keyCodewłaściwość jak keydown. Klawisz Home ma keyCodena moim komputerze 36 znaków w Firefoksie, który jest kodem znaków dla „$”, co uniemożliwiłoby rozróżnienie między naciśnięciem klawisza Home a użytkownikiem wpisującym znak $ event.which || event.keyCode.
Tim Down
32

jQuery normalizuje się w event.whichzależności od tego event.which, event.keyCodeczy event.charCodejest obsługiwana przez przeglądarkę:

// Add which for key events
if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
   event.which = event.charCode != null ? event.charCode : event.keyCode;
}

Dodatkową zaletą .whichjest to, że jQuery robi to również dla kliknięć myszką:

// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && event.button !== undefined ) {
    event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
}
David Tang
źródło
2
var key = event.which || event.charCode || event.keyCode
Anne van Rossum
@ anne-van-rossum, event.wich == null && ...test na wartość zerową lub tylko niezdefiniowaną. twój event.wich || ...test na fałsz (niezdefiniowany, zerowy, fałszywy, 0, '' itd.)
aMarCruz
@aMarCruz Falsy celowo. Np. Bugs.webkit.org/show_bug.cgi?id=16735 z raportowaniem Webkit 0. I nie sądzę, żeby sprawdzać ""czy []boli.
Anne van Rossum
20

Jeśli korzystasz z waniliowego Javascript, pamiętaj, że keyCode jest już nieaktualny i zostanie usunięty:

Ta funkcja została usunięta ze standardów internetowych. Chociaż niektóre przeglądarki mogą go obsługiwać, jest on w trakcie usuwania. Unikaj go i aktualizuj istniejący kod, jeśli to możliwe; zapoznaj się z tabelą kompatybilności na dole tej strony, aby podjąć decyzję. Pamiętaj, że ta funkcja może przestać działać w dowolnym momencie

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

Zamiast tego użyj: .key lub .code w zależności od pożądanego zachowania: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code https://developer.mozilla.org/en -US / docs / Web / API / KeyboardEvent / key

Oba są zaimplementowane w nowoczesnych przeglądarkach.

slykat
źródło
.code odpowiada fizycznej lokalizacji klawisza na klawiaturze, natomiast .key odpowiada znakowi wygenerowanemu przez naciśnięcie klawisza niezależnie od lokalizacji.
Christopher
1
Zarówno „kod”, jak i „klucz” mają dziwactwa we współczesnych przeglądarkach. Użycie przykładu „Wypróbuj” na MDN developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code w różnych przeglądarkach pokazuje, że IE11 / IE Edge nie implementuje „kodu” i „klucza” implementacja nie pasuje do implementacji w Chrome / FF / Safari (wydaje się, że różnice dotyczą głównie znaków kontrolnych, takich jak Escape i Enter). Myślę, że korzystanie z biblioteki może być najłatwiejsze, chyba że sam zechcesz wziąć pod uwagę te kaprysy. Naprawdę chcę, aby to była odpowiedź, ale IE
spieprzy
Hmm ... właściwie to nie wygląda tak źle, aby zaimplementować klucz w przeglądarce. Zwykłe klawisze alfanumeryczne po prostu zwracają swoją wartość, a klawisze sterujące (klawisz Escape, Enter, Tab itp.) Pojawiają się identycznie w większości przeglądarek oprócz IE11 / Edge, które implementują starszą wersję specyfikacji, więc dla każdej z nich są tylko dwie możliwe wartości klucz.
Akrikos
Radziłbym używać keyzamiast code. Na przykład, jeśli masz klawiaturę z klawiszami sterowania multimediami, naciśnięcie przycisku Odtwarzaj / Wstrzymaj powoduje wyświetlenie „MediaPlayPause” dla keyi „” dla code.
thdoan
6

spójrz na to: https://developer.mozilla.org/en-US/docs/Web/API/event.keyCode

W przypadku naciśnięcia klawisza wartość Unicode wciśniętego klawisza jest przechowywana we właściwości keyCode lub charCode, nigdy w obu przypadkach. Jeśli naciśnięty klawisz generuje znak (np. „A”), charCode jest ustawiany na kod tego znaku, z uwzględnieniem wielkości liter. (tzn. charCode bierze pod uwagę, czy klawisz Shift jest wciśnięty). W przeciwnym razie kod naciśniętego klawisza jest zapisywany w keyCode. keyCode jest zawsze ustawiany w zdarzeniach keydown i keyup. W takich przypadkach charCode nigdy nie jest ustawiony. Aby uzyskać kod klucza, niezależnie od tego, czy został zapisany w keyCode czy charCode, zapytaj, która właściwość. Znaki wprowadzone za pomocą edytora IME nie rejestrują się za pomocą keyCode ani charCode.

Lew
źródło
6

Polecam event.keyobecnie. Dokumenty MDN: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

event.KeyCodei event.whichoba mają nieprzyjemne przestarzałe ostrzeżenia na górze swoich stron MDN:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode https://developer.mozilla.org/en-US / docs / Web / API / KeyboardEvent / which

W przypadku klawiszy alfanumerycznych event.keywydaje się być implementowany identycznie we wszystkich przeglądarkach. W przypadku klawiszy sterujących (tab, enter, escape itp.) event.keyMa tę samą wartość w Chrome / FF / Safari / Opera, ale inną wartość w IE10 / 11 / Edge (IE najwyraźniej używają starszej wersji specyfikacji, ale pasują do siebie, ponieważ z 14 stycznia 2018 r.).

W przypadku klawiszy alfanumerycznych czek wyglądałby następująco:

event.key === 'a'

W przypadku znaków kontrolnych musisz zrobić coś takiego:

event.key === 'Esc' || event.key === 'Escape'

Użyłem tutaj tego przykładu do testowania na wielu przeglądarkach (musiałem otworzyć w codepen i edytować, aby uruchomić go z IE10): https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ kod

event.code jest wymieniony w innej odpowiedzi jako możliwość, ale IE10 / 11 / Edge nie implementuje go, więc nie działa, jeśli chcesz obsługi IE.

Akrikos
źródło
2

Solidna biblioteka JavaScript do przechwytywania danych z klawiatury i wprowadzonych kombinacji klawiszy. Nie ma zależności.

http://jaywcjlove.github.io/hotkeys/

hotkeys('ctrl+a,ctrl+b,r,f', function(event,handler){
    switch(handler.key){
        case "ctrl+a":alert('you pressed ctrl+a!');break;
        case "ctrl+b":alert('you pressed ctrl+b!');break;
        case "r":alert('you pressed r!');break;
        case "f":alert('you pressed f!');break;
    }
});

Klawisze skrótu rozumie następujących wyrażeń: , shift, option, , alt, ctrl, control, command, i .

Następujące klawisze specjalne mogą być wykorzystywane do skrótów: backspace, tab, clear, enter, return, esc, escape, space, up, down, left, right, home, end, pageup, pagedown, del, deletei f1dzięki f19.

小弟 调 调
źródło
Jednak przesuwa Array.prototype.indexOf, więc jeśli używasz tego w innej bibliotece, może nie być odpowiedni, ponieważ modyfikuje zasięg globalny. Wydaje się również, że używa przestarzałych event.keyCode.
Akrikos
Ta biblioteka nie wykryła Fn na moim laptopie Vaio.
thdoan
0

W przeglądarce Firefox właściwość keyCode nie działa w przypadku zdarzenia onkeypress (zwraca tylko 0). W przypadku rozwiązania dla różnych przeglądarek użyj właściwości what wraz z keyCode, np .:

var x = event.which || event.keyCode;  // Use either which or keyCode, depending on browser support
Pankaj Chauhan
źródło