最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I keep the focus on an input, after i click on a button without flickering in Vue 3? - Stack Overflow

programmeradmin1浏览0评论

Script

const amountRef = ref(null);
const amount = ref(0.1);

const insertSuggestion = (e, value) => {
  e.preventDefault();
  e.stopPropagation();
  amount.value = value;
  amountRef.value.focus();
};

Template

<Suggestion
   class="..."
   v-for="suggestion in suggestions"
   :key="suggestion"
   @click="insertSuggestion($event, suggestion)"
>
    {{ suggestion }}
</Suggestion>
<input
   class="..."
   @keyup.enter="handleBuy"
   placeholder="Amount"
   ref="amountRef"
   v-model="amount"
/>

Script

const amountRef = ref(null);
const amount = ref(0.1);

const insertSuggestion = (e, value) => {
  e.preventDefault();
  e.stopPropagation();
  amount.value = value;
  amountRef.value.focus();
};

Template

<Suggestion
   class="..."
   v-for="suggestion in suggestions"
   :key="suggestion"
   @click="insertSuggestion($event, suggestion)"
>
    {{ suggestion }}
</Suggestion>
<input
   class="..."
   @keyup.enter="handleBuy"
   placeholder="Amount"
   ref="amountRef"
   v-model="amount"
/>

Share Improve this question asked May 12, 2021 at 10:19 oemeraoemera 3,4533 gold badges22 silver badges39 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

Stop the de-focusing with @pointerdown.prevent

TLDR: pointerdown (or mousedown) occurs before blur (or click), so use it to prevent subsequent default events that occur when the click or tap is finished.

NOTE: I believe you can use pointerdown or mousedown events interchangeably.

I strongly advise avoiding any focus change at all, even if it's a re-focus, as any state change may invoke a cascade of secondary state changes especially if used with some deeply nested ponents. Even if it works, at the least you risk a visual "hiccup" exposed to the user (yuck).

Instead, you should try to actually stop the de-focusing from happening in the first place.

You had the right idea with @click and a subsequent e.preventDefault(), but a click event occurs after blurring.

Instead, make the preventDefault occur before blur occurs, by triggering it from an earlier event, pointerdown, which occurs before blur & click.

Simply add Vue's @pointerdown.prevent on elements where, when clicked, you don't want another element (on the page) to de-focus. With this, the OP can get rid of a bunch of lines:

Script

const insertSuggestion = (value) => {
  // NOT NEEDED ANYMORE:
  // e.preventDefault();
  // e.stopPropagation();
  // amountRef.value.focus();

  // KEEP:
  amount.value = value
}

Template

<Suggestion
   class="..."
   v-for="suggestion in suggestions"
   :key="suggestion"
   @pointerdown.prevent
   @click="insertSuggestion(suggestion)"
>
    {{ suggestion }}
</Suggestion>

You can re-focus the input element on the blur event:

<input ref="amountRef" @blur="$refs.amountRef.focus()"/>

Edit

You also need to check the relatedTarget of the blur event to make sure you only re-focus when one of the buttons is clicked.

Note: this solution does not work on Firefox.

<Suggestion
   class="suggestion-btn"
   ...
>
</Suggestion>
<input
   ref="amountRef"
   @blur="onBlur"
/>

onBlur(evt) {
    if (
        evt.relatedTarget &&
        evt.relatedTarget.classList.contains("suggestion-btn")
    ) {
        this.$refs.amountRef.focus();
    }
},

You could try to capture the blur event and add the classes back if the relatedTarget is one of those buttons. Super psuedo code below:

<input
   class="..."
   @keyup.enter="handleBuy"
   @blur="maybeMimicFocus"
   placeholder="Amount"
   ref="amountRef"
   v-model="amount"
/>
maybeMimicFocus (event) {
  if (event.relatedTarget && event.relatedTarget.tagname === 'btn') {
    this.$refs.amountRef.$el.classList.add('the-classes-that-make-it-look-focused')
  }
}

the browser won't have to repaint the dom and therefore this transaction should be so quick that the naked eye won't see it a difference. the only caveat I can see is if there are animations attached to transitioning properties in which those will have to fire.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论