keypress event doesn't log input value first time event is fired

老子叫甜甜 提交于 2020-06-14 15:04:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!