问题
The first time a keypress
event fires, it logs an empty input value even though the input has a value. The second time it logs the value but is one keystroke behind in comparison with the input's value. You can check this behavior on the next example:
document.addEventListener('DOMContentLoaded', () =>
{
const input = document.querySelector('input');
input.addEventListener('keypress', e =>
{
console.log(e.target.value);
});
});
<input type="text"/>
However, the next workaround makes it work, even though I pass in 0ms
.
document.addEventListener('DOMContentLoaded', () =>
{
const input = document.querySelector('input');
input.addEventListener('keypress', e =>
{
setTimeout(() => console.log(e.target.value), 0);
});
});
<input type="text"/>
Why is this hapenning?
回答1:
When you press a key
for the first time, the value assigned to the input is empty
at the time the keypress
event takes place, then the character is added to the input, but a moment later. This same is valid for future keypress
events, the value of the input
you read is the previous before the input changes
. Also, if you read on the MDN there is a warning about keypress being dropped. Hence, and instead, you may want to listen on keyup
event as shown on the next example:
const input = document.querySelector('input');
input.addEventListener('keyup', e =>
{
console.log(e.target.value);
});
.as-console {background-color:black !important; color:lime;}
<input type="text" id="input">
回答2:
keypress
event dont change input value
- you read 'old' value - current key is in e.key
document.addEventListener('DOMContentLoaded', () => {
const input = document.querySelector('input');
input.addEventListener('keypress', e => {
console.log('value',e.target.value);
console.log('key',e.key);
});
});
<input>
you can use onkeyup
event to have current value in event.target.value
document.addEventListener('DOMContentLoaded', () => {
const input = document.querySelector('input');
input.addEventListener('keyup', e => {
console.log('value', e.target.value);
console.log('key', e.key);
});
});
<input>
The input value will be update before setTimeout
function will be executed (even for 0 ms) - keyword: js event loop
回答3:
According to jQuery docs:
The keypress event is sent to an element when the browser registers keyboard input. This is similar to the keydown event, except that modifier and non-printing keys such as Shift, Esc, and delete trigger keydown events but not keypress events. Other differences between the two events may arise depending on platform and browser.
The keyup event is sent to an element when the user releases a key on the keyboard.
The oninput event it's an event that triggers whenever the input changes.
So the keypress
will be fired before the value change, use keyup
instead
About the setTimeout
, when you put the codes in that place, it will be Asynchronous function (even for 0 ms). In javascript, the Asynchronous function will be executed after all Synchronous commands are finished
回答4:
That's because it's being fired before the input value is updating. You can try using keyUp
instead of keyPress
.
回答5:
The keyup
event fires when the key is released which generates the feeling of a little delay. I'd rather prefer to use the keydown
event which have the same behavior as the OP is exposing. (Note that the keypress
event is now deprecated).
Instead of waiting for the next tick (by using setTimeout
) you can concatenate the current value with the pressed key:
document.addEventListener('DOMContentLoaded', () => {
const input = document.getElementById('input');
input.addEventListener('keydown', event => {
console.log(event.target.value + event.key);
});
});
<input type="text" id="input">
EDIT: After trying this solution a little more, it fails to work as expected when moving the cursor between the input text or when reaching a maxlength
, so after all I ended up using the workaround proposed by the OP with setTimeout
and a timeout of 0
来源:https://stackoverflow.com/questions/56248925/keypress-event-doesnt-log-input-value-first-time-event-is-fired