simplesmiler / vue-focus

A reusable focus directive for reusable Vue.js components
MIT License
406 stars 40 forks source link

Prevent re-focus when unrelated element attribute changes #8

Closed simshaun closed 7 years ago

simshaun commented 7 years ago

Take a look at the following fiddle. When the form is submitted, the submit button is disabled temporarily. The attribute change on a seemingly unrelated element is causing vue-focus to re-focus on the text input.

I'm not sure if this is vue-focus's problem, or something I don't understand about how Vue handles rendering DOM updates.

https://jsfiddle.net/simshaun/rhqoL2hn/

Edit

This has something to do with the focus directive hooking into componentUpdated. Adding a console.log in it shows that it's being executed even when unrelated elements are changed by Vue.

simplesmiler commented 7 years ago

Hi, thanks for the report. The behavior is technically correct, but undesirable in this case.

This happens because in Vue 2.0 there is only one reactive watcher per component (as opposed to watcher per expression in 1.x), so directives receive updates when anything in the host component changes (as opposed to when the expression value changes in 1.x).

This can be fixed by comparing old value with a new one in the update handler, and only doing focus/blur when value changes (including the initialization). The question though is whether this would be a breaking change, i.e. whether there is a use case for calling focus/blur on every change. If this would be a breaking change, I'd prefer adding this behavior under a modifier (something like .lazy).

What do you think?

simshaun commented 7 years ago

I can't think of any cases where I'd want the input to automatically receive focus when anything else changes. In cases where that type of behavior is desirable, it's explicitly programmed. Perhaps a modifier would be best, or release a 3.x. I think anybody coming from 1.x would expect the 1.x behavior & not this new 2.x behavior though.

simplesmiler commented 7 years ago

Released in 2.1.0. Demo (using rawgit instead of cdnjs): https://jsfiddle.net/rhqoL2hn/3/