脚本
const amountRef = ref(null);
const amount = ref(0.1);
const insertSuggestion = (e, value) => {
e.preventDefault();
e.stopPropagation();
amount.value = value;
amountRef.value.focus();
};
模板
<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"
/>
您可以将输入元素重新聚焦在
blur
事件上:
<input ref="amountRef" @blur="$refs.amountRef.focus()"/>
编辑
您还需要检查
relatedTarget
事件的 blur
,以确保仅在单击其中一个按钮时重新聚焦。
注意:此解决方案不适用于 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();
}
},
如果
relatedTarget
是这些按钮之一,您可以尝试捕获模糊事件并将类添加回来。超级伪代码如下:
<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')
}
}
浏览器不必重新绘制 dom,因此该事务应该很快,肉眼看不出有什么不同。我能看到的唯一警告是是否有附加到过渡属性的动画,其中这些动画必须触发。
TLDR:
mousedown
出现在 blur
或 click
之前。
我强烈建议完全避免任何焦点更改,甚至重新焦点,因为任何状态更改都可能引发一系列二级状态更改,特别是与某些深度嵌套的组件一起使用时。即使它有效,您也会面临向用户暴露视觉“打嗝”的风险。
相反,您应该首先尝试真正阻止散焦的发生。
您对
@click
和随后的 e.preventDefault()
的想法是正确的,但是在模糊之后发生了点击事件。
相反,通过从较早的事件
preventDefault
(该事件发生在模糊和单击之前)触发它,使 mousedown
发生在模糊发生之前。只需添加 Vue 的
@mousedown.prevent
来停止失焦,然后你也可以摆脱一堆后续行:
脚本
const insertSuggestion = (value) => {
amount.value = value
}
模板
<Suggestion
class="..."
v-for="suggestion in suggestions"
:key="suggestion"
@mousedown.prevent
@click="insertSuggestion(suggestion)"
>
{{ suggestion }}
</Suggestion>