Unexpected @keyup triggering on focused input field when navigated to via keyboard "click"
Vue version
3.3.8
Link to minimal reproduction
https://stackblitz.com/edit/github-qhj1am
Steps to reproduce
Note: Issue relates to keyboard navigation! - not mouse.
- Open index (Home) page and tab bring focus to button labelled Goto Two.
- Hit enter key to effectively click button. (remember, keyboard - not mouse!)
- Browser navigates to page two
- Notice the text highlighting that the
@keyup
event has been triggered on the focused input field on the destination page.
I can't think why this should be expected behaviour. Almost as if the keyup
event from pressing the enter button on the index page is being seen by page two when the focus()
call is made?!
Open the browser devtools to see console.log messages also show the flow of lifecycle and other events firing.
Also, to add additional context/relevant to help diagnose the error. In the script for page Two.vue there is another option (2) that can be uncommented and option (1) commented out. This only calls focus() after a delay. With this in place the issue doesn't happen.
What is expected?
My expectation is that keyboard events generated by the Home page have been cancelled by the time the router moves to the destination page.
What is actually happening?
It appears that the keyboard generated click
event from pressing enter
key on Home page is also generating a keyup
event that lives long enough to trigger a keyup
event on the new route/page.
System Info
System:
OS: macOS 13.6.2
CPU: (12) arm64 Apple M2 Pro
Memory: 79.48 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 18.18.2 - ~/.nvm/versions/node/v18.18.2/bin/node
npm: 9.8.1 - ~/.nvm/versions/node/v18.18.2/bin/npm
Browsers:
Chrome: 119.0.6045.159
Safari: 17.1
Any additional comments?
I experienced this on Nuxt and after posting on Nuxt repo was advised to check whether it could be reproduced as a vue issue which I did.
This issue is disguised whenever the site has page transitions enabled as I assume that provides a suitable delay for the keyup events to dissipate.
Additional, self-evident but the focus()
is a key aspect of this reproduction as without the input control being focused the keyup won't fire.
Thanks for your help with this!
This is not particularly suprising, I think. The keyup event fires when your finger has left the key. But because Vue/Nuxt renders the new view so fast, that update and the application of the focus to that input happen before you lift up your finger.
So the keyup event fires after the route has been changed and the focus has been applied to the input.
See here for a plain JS demo:
https://jsfiddle.net/mreqL01w/
Depending on how fast you hit/let go of enter, you can trigger this reliably with the set 100ms timeout.
if you change the timeout from 100ms to something like 300ms, your enter key stroke will typically no longer trigger the keyup.
Solution: Use an adiditional keydown event and some kind of variable you check in the keyup event handler to assure that the keyup event was in fact triggered from that input.