OnKeyPress Vs. onKeyUp и onKeyDown

329

В чем разница между этими тремя событиями? Погуглив, я обнаружил, что:

  • onKeyDownСобытие срабатывает , когда пользователь нажимает клавишу.
  • onKeyUpСобытие срабатывает , когда пользователь отпускает клавишу.
  • onKeyPressСобытие срабатывает , когда пресса и пользователь отпускает ключ ( с onKeyDownпоследующим onKeyUp).

Я понимаю первые два, но не onKeyPressтак onKeyUpли? Можно ли отпустить клавишу ( onKeyUp), не нажимая ее ( onKeyDown)?

Это немного сбивает с толку, может кто-нибудь прояснить это для меня?

instantsetsuna
источник
3
Я обнаружил, что если я удерживаю клавишу TAB, она непрерывно перебирает все поля и вызывает только «onkeydown».
Ню Эверест
23
Событие нажатия клавиши представляет набираемый символ, который можно использовать для ввода, например, «a», «D», «£», «©» и т. д. С другой стороны, события keydown и keyup представляют ЛЮБЫЕ набираемые клавиши, которые включают в себя такие вещи, как возврат, вкладка, вверх, вниз, домой, конец и т.
skcin7
2
«(или можно отпустить клавишу (KeyUp), не нажимая (KeyDown) это?)» - Да. Например, клавиша табуляции: событие keyup не может быть захвачено тем же элементом, что и keydown.
самоочевидный

Ответы:

191

Проверьте здесь архивную ссылку, первоначально использованную в этом ответе.

По этой ссылке:

В теории onKeyDownи onKeyUpсобытия представляют собой ключи нажаты или отпущены, в то время как onKeyPressсобытие представляет собой символ набираясь. Реализация теории не одинакова во всех браузерах.

DCP
источник
18
Соберите jsfiddle, основанный на посте @ Falk, чтобы продемонстрировать особенности (используя jquery): jsfiddle.net/zG9MF/2
fordareh
Я не вижу связанной страницы, но пункт о «набираемом символе» важен, если вы планируете использовать его для любого вида проверки. Событие нажатия клавиши не срабатывает, когда пользователь удаляет символ, поэтому проверка не сработает.
Тони Мэррифилд,
@ Тони Меррифилд - ссылка работает нормально для меня, я только что проверил это снова.
декабря
1
@dcp - Да, подсказки было достаточно, чтобы я встал на правильный путь. Я только добавил свой комментарий, чтобы подчеркнуть, что событие срабатывает только тогда, когда набирается символ, а не какое-либо нажатие клавиши - вы получили мое повышение;)
Тони Мэррифилд
1
Кроме того, при «долгом» нажатии клавиши событие KeyDown продолжает срабатывать до тех пор, пока клавиша не будет отпущена, и в этом случае KeyUp срабатывает только один раз;)
Bernoulli IT
195

KeyPress, KeyUpИ KeyDownаналогичны, соответственно: Click, MouseUp,и MouseDown.

  1. Down случается первым
  2. Press происходит второй (при вводе текста)
  3. Up происходит в последний раз (когда ввод текста завершен).

Исключением является webkit , в котором есть дополнительное событие:

keydown
keypress
textInput     
keyup

Ниже приведен фрагмент, который вы можете использовать, чтобы увидеть, когда события будут запущены:

window.addEventListener("keyup", log);
window.addEventListener("keypress", log);
window.addEventListener("keydown", log);

function log(event){
  console.log( event.type );
}

Робусто
источник
1
Итак, является ли KeyPress просто дополнительным событием, которое является ч / б KeyDown и TextInput? Как он (KeyPress) обычно используется разработчиками?
instantsetsuna
78
+1 лучший ответ - * Вниз происходит первым, * Нажатие происходит вторым (при вводе текста), а * Вверх происходит последним (после завершения ввода текста).
Скотт Пелак
2
-1 потому что небольшой эксперимент во фрагменте противоречит вашей аналогии с событием click. Событие 'click' запускается одновременно с 'mouseup' (когда вы отпускаете кнопку мыши), но событие 'keypress' запускается одновременно с 'keydown' (когда клавиша нажата в первый раз).
Марк Амери
2
@Robusto Собственно, keypressи keydownсобытия в буквальном смысле получить присваивается такое же .timeStampзначение, которое с точностью до интервалами 5 микросекунд, но это не моя точка в любом случае. Я clickхочу сказать, что событие не сработает до тех пор, пока вы не отпустите кнопку мыши, поэтому если вы говорите, что keypressэта версия клавиатуры clickделает его звучащим так keypressже, оно не сработает, пока вы не отпустите клавишу. На самом деле это не так: он срабатывает, когда клавиша нажата, так же, как и keydownона. Так keypressчто на самом деле совсем не аналогично click.
Марк Амери
2
@Robusto «как вы объясните« нажатие клавиши », всегда записываемое после« нажатия клавиши »» - просто: одно и то же действие пользователя (нажатие клавиши) сразу же запускает оба обработчика, которые будут помещены в очередь событий, но в фиксированном порядке , «Вы просто хотите иметь аргумент ради аргумента» - а? Ядро тезис вашего ответа заключается в том , что keypress, keyupи keydownаналогичны click, mouseupи mousedown. Для меня естественная интерпретация этого состоит в том, что keypressогонь срабатывает в одно и то же время, что и keyup(так же, как clickи mouseup). Что вы имели в виду, если не это?
Марк Амери
23

Большинство ответов здесь сосредоточены больше на теории, чем на практических вопросах, и есть некоторые большие различия между значениями полей ввода keyupи keypressотносительно них, по крайней мере в Firefox (протестировано в 43).

Если пользователь вводит 1пустой элемент ввода:

  1. Значением входного элемента будет пустая строка (старое значение) внутри keypressобработчика

  2. Значение входного элемента будет 1(новое значение) внутри keyupобработчика.

Это очень важно, если вы делаете что-то, что зависит от знания нового значения после ввода, а не текущего значения, такого как встроенная проверка или автоматическое табулирование.

Сценарий:

  1. Пользователь вводит 12345в элемент ввода.
  2. Пользователь выбирает текст 12345.
  3. Пользователь печатает письмо A.

Когда keypressсобытие начинается после ввода буквы A, текстовое поле теперь содержит только букву A.

Но:

  1. Field.val () есть 12345.
  2. $ Field.val (). Длина 5
  3. Выбор пользователя - пустая строка (вы не можете определить, что было удалено, перезаписав выбор).

Таким образом, кажется, что браузер (Firefox 43) стирает выбор пользователя, затем запускает keypressсобытие, затем обновляет содержимое полей, а затем запускает keyup.

Ник
источник
16

onkeydownвызывается , когда клавиша нажата (например , в ярлыках, например, в Ctrl+A,Ctrl удерживается «нажата».

onkeyup срабатывает при отпускании ключа (включая ключи модификатора / etc)

onkeypressсрабатывает как комбинация onkeydownи onkeyup, или в зависимости от повторения клавиатуры (когда onkeyupне срабатывает). (Это повторяющееся поведение я не проверял. Если вы делаете тест, добавьте комментарий!)

textInput(только webkit) запускается, когда вводится какой-либо текст (например, Shift+Aон вводит заглавную букву «A», но Ctrl+Aвыбирает текст и не вводит текстовый ввод. В этом случае запускаются все остальные события)

arunjitsingh
источник
1
Просто подтвердил, что действительно, «onkeypress» вызывается повторно, когда клавиша удерживается нажатой, и происходит «повтор клавиатуры». Тем не менее, это также верно для "onkeydown"! (что неожиданно, учитывая имя)
Venryx
11

Во-первых, они имеют разное значение: они стреляют

  • KeyDown - когда клавиша была нажата
  • KeyUp - когда была отпущена нажатая кнопка , и после обновления значения input / textarea (единственное из них)
  • KeyPress - между ними и вовсе не означает, что клавиша была нажата и отпущена (см. Ниже).

Во-вторых, некоторые ключи запускают некоторые из этих событий и не запускают другие . Например,

  • KeyPress игнорирует delete, стрелки, PgUp/ PgDn, home/ end, ctrl, alt, и shiftт.д. , а KeyDown и KeyUp не (см подробности о escниже);
  • когда вы переключаете окно с помощью alt+ tabв Windows, altсрабатывает только KeyDown для запуска, потому что переключение окна происходит до любого другого события (и KeyDown для tabпредотвращается системой, я полагаю, по крайней мере, в Chrome 71).

Кроме того, вы должны иметь в виду, что event.keyCodeevent.which) обычно имеют одинаковые значения для KeyDown и KeyUp, но разные для KeyPress. Попробуйте игровую площадку, которую я создал. Кстати, я заметил довольно странную причину: в Chrome, когда я нажимаю ctrl+, aа input/ textareaпусто, KeyPress срабатывает с event.keyCodeevent.which), равным1 ! (когда вход не пустой, он вообще не срабатывает).

Наконец, есть некоторые прагматики :

  • Для обработки стрелок вам, вероятно, потребуется использовать onKeyDown: если пользователь удерживает клавишу , KeyDown срабатывает несколько раз (в то время как KeyUp срабатывает только один раз, когда они отпускают кнопку). Кроме того, в некоторых случаях вы можете легко предотвратить распространение KeyDown, но не можете (или не можете так просто) предотвратить распространение KeyUp (например, если вы хотите отправить при вводе без добавления новой строки в текстовое поле).
  • Удивительно, но когда вы держите клавишу, скажем textarea, и KeyPress, и KeyDown срабатывают несколько раз (Chrome 71), я бы использовал KeyDown, если мне нужно событие, которое запускается несколько раз, и KeyUp для отпускания одного ключа.
  • KeyDown обычно лучше для игр, когда вы должны обеспечить лучшую реакцию на их действия.
  • escобычно обрабатывается через KeyDown: KeyPress не срабатывает и KeyUp ведет себя по-разному для inputs и textareas в разных браузерах (в основном из-за потери фокуса)
  • Если вы хотите настроить высоту текстовой области для содержимого, вы, вероятно, не будете использовать onKeyDown, а скорее onKeyPress ( PS хорошо, на самом деле лучше использовать onChange для этого случая ).

Я использовал все 3 в своем проекте, но, к сожалению, возможно, забыл некоторые прагматики. (чтобы отметить: есть также inputи changeсобытия)

YakovL
источник
Я не думал о добавлении новой строки в содержимое поля, но это действительно важно.
FKEinternet
10

Эта статья Яна Вольтера - лучшая статья, которую я когда-либо встречал, вы можете найти архивную копию здесь, если ссылка не работает.

Он хорошо объясняет все ключевые события браузера,

KeyDown событие происходит при нажатии на клавишу, а затем сразу же событие нажатия клавиши. Затем событие keyup генерируется при отпускании ключа.

Чтобы понять разницу между KeyDown и нажатием клавиши , полезно различать символы и ключи . Ключ является физической кнопкой на клавиатуре компьютера. Символ является символом набран нажатием кнопки. На клавиатуре США нажатие 4клавиши при удерживании Shiftклавиши обычно приводит к появлению символа «знак доллара». Это не обязательно так на каждой клавиатуре в мире. Теоретически события keydown и keyup представляют собой нажатие или отпускание клавиш, а нажатие клавишисобытие представляет вводимый символ. На практике это не всегда так, как это реализовано.

Некоторое время некоторые браузеры запускали дополнительное событие, называемое textInput , сразу после нажатия клавиши . Ранние версии стандарта DOM 3 задумывали это как замену события нажатия клавиши , но позже это понятие было отменено. Webkit поддерживал это между версиями 525 и 533, и мне сказали, что IE поддерживал это, но я никогда не обнаруживал этого, возможно, потому что Webkit требовал, чтобы он назывался textInput, в то время как IE называл его textinput .

Существует также событие под названием input , поддерживаемое всеми браузерами, которое вызывается сразу после внесения изменений в текстовое поле или поле ввода. Обычно срабатывает нажатие клавиши, затем в текстовой области появляется напечатанный символ, а затем срабатывает ввод. Вход событие фактически не дает никакой информации о том, что было напечатан ключ - вы должны проверить текстовое поле , чтобы понять это , что изменилось - так что мы на самом деле не считаем это ключевым событием и действительно не документировать его здесь , Хотя изначально он был определен только для текстовых областей и полей ввода, я полагаю, что есть некоторое движение к его обобщению для стрельбы и по другим типам объектов.

Сурадж Джейн
источник
Лучший ответ, так как вы можете получить, скажем, символ доллара от нажатия клавиши?
блюджайке
10

Кажется, что onkeypress и onkeydown делают одно и то же (с небольшой разницей в сочетаниях клавиш, уже упомянутых выше).

Вы можете попробовать это:

<textarea type="text" onkeypress="this.value=this.value + 'onkeypress '"></textarea>
<textarea type="text" onkeydown="this.value=this.value + 'onkeydown '" ></textarea>
<textarea type="text" onkeyup="this.value=this.value + 'onkeyup '" ></textarea>

И вы увидите, что события onkeypress и onkeydown запускаются при нажатии клавиши, а не при нажатии клавиши.

Разница в том, что событие вызывается не один, а многократно (пока вы удерживаете нажатой клавишу). Помните об этом и обращайтесь с ними соответствующим образом.

Фальк
источник
Клавиши Ctrl, Shift, CapsLock, Backspace и другие, которые ничего не вводят, не вызываютkeypress события, но всегда вызывают a keydown.
CPHPython
8

Событие onkeypress работает для всех клавиш, кроме ALT, CTRL, SHIFT, ESC во всех браузерах, где событие onkeydown работает для всех клавиш. Означает событие onkeydown захватывает все ключи.

Мохд Садик
источник
нажатие клавиши также игнорирует удаление, стрелки, начало / конец, PgUp / PgDn, подробности смотрите в моем ответе (вы также можете обновить свой ответ)
YakovL
4

Просто хотел поделиться любопытством

при использовании события onkeydown для активации метода JS код для этого события НЕ совпадает с кодом, полученным с помощью onkeypress!

Например, цифровые клавиши вернут те же коды, что и цифровые клавиши над буквенными клавишами при использовании onkeypress, но НЕ при использовании onkeydown!

Мне понадобилось несколько секунд, чтобы понять, почему мой скрипт, который проверял определенные коды, не работал при использовании onkeydown!

Демонстрация: https://www.w3schools.com/code/tryit.asp?filename=FMMBXKZLP1MK

и да. Я знаю, что определения методов разные ... но очень запутанно то, что в обоих методах результат события извлекается с использованием event.keyCode ... но они не возвращают одно и то же значение ... не очень декларативная реализация.

ударник
источник
Оказывается , что все такие же , для числовых символов ( 0123456789)
Mrigank Pawagi
А вы заметили, что keyDown дает KEY на клавиатуре, в то время как keyPress дает точный символ, который мы только что набрали (или нажали)
Mrigank Pawagi
2

По сути, эти события действуют по-разному в разных типах и версиях браузера, я создал небольшой тест jsBin, и вы можете проверить консоль, чтобы узнать, как эти события ведут себя в вашей целевой среде, надеюсь, это поможет. http://jsbin.com/zipivadu/10/edit

Кен Чан
источник
1

Обновленный ответ:

KeyDown

  • Срабатывает несколько раз, когда вы удерживаете клавиши.
  • Запускает мета-ключ.

Нажатие клавиши

  • Срабатывает несколько раз, когда вы удерживаете клавиши.
  • Разве не срабатывает мета ключи.

KeyUp

  • Срабатывает один раз в конце, когда вы отпускаете ключ.
  • Запускает мета-ключ.

Это поведение в обоих addEventListenerи jQuery.

https://jsbin.com/vebaholamu/1/edit?js,console,output <- попробовать пример

показывает пример с удержанием для SSS

(ответ был отредактирован с правильным ответом, скриншот и пример)

Куанг Ван
источник
За исключением keydown, который срабатывает также несколько раз
bluejayke
-1, потому что хотя бы одна деталь по этому поводу неправильна хотя бы в Chrome; как говорит @bluejayke, KeyDown также срабатывает многократно, когда вы удерживаете клавишу.
Марк Амери
Да, вы правы, извините за мою ошибку; ответ отредактирован.
Куанг Ван
0

Несколько практических фактов, которые могут быть полезны, чтобы решить, какое событие обрабатывать (запустите скрипт ниже и сфокусируйтесь на поле ввода):

$('input').on('keyup keydown keypress',e=>console.log(e.type, e.keyCode, e.which, e.key))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input/>

Нажатие кнопки:

  • не вводящие / печатающие ключи (например Shift, Ctrl) не будут вызывать keypress. Нажмите Ctrlи отпустите:

    keydown 17 17 Контроль

    keyup 17 17 Control

  • ключи от клавиатур, которые применяют преобразования символов к другим символам, могут привести к « мертвым» и дублирующим «ключам» (например ~, ´) keydown. Нажмите ´и отпустите, чтобы отобразить двойное ´´:

    Keydown 192 192 Dead

    keydown 192 192 ´´

    нажатие клавиши 180 180 ´

    нажатие клавиши 180 180 ´

    Keyup 192 192 Dead

Кроме того, ввод без ввода (например, ранжированный <input type="range">) будет по-прежнему запускать все события нажатия клавиш, нажатия клавиш и нажатия клавиш в соответствии с нажатыми клавишами.

CPHPython
источник