如何将焦点设置在新(自动)渲染的dom元素上



我有一个输入字段,它会自动替换为文本区域和相同的内容,具体取决于用户输入的字符数:

<textarea v-if="myString.length > 20" v-model="myString"/>
<input type="text" v-if="myString.length <= 20" v-model="myString"/>

我遇到的问题是,当用户输入第21个字符时,焦点会丢失。因此,用户会感到恼火,因为当他键入第22个字符时,它不会出现在文本区域(没有焦点(。然后如何将焦点设置在新渲染的文本区域这里的问题是它会自动渲染。否则,我可以在文本区域设置一个ref并调用focus((。

另一个问题是删除了第21个字符,并从文本区域切换回输入elment。

您可以将textarea/input封装在组件中,并使用其mounted钩子调用其focus(),如该组件所示:

<!-- AutoFocusedInput.vue -->
<script setup>
import { ref, onMounted, computed, nextTick } from 'vue'
const input = ref()
onMounted(async () => {
await nextTick()
input.value.focus()
})
const props = defineProps({
modelValue: String,
textarea: Boolean,
})
const comp = computed(() => (props.textarea ? 'textarea' : 'input'))
</script>
<template>
<component
:is="comp"
ref="input"
v-bind="$attrs"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<AutoFocusedInput textarea v-if="myString.length > 20" v-model="myString" />
<AutoFocusedInput v-else v-model="myString" />

演示

虽然这在技术上是可能的,但这种用户体验可能并不理想,您应该考虑其他不需要像这样集中输入的设计(如@kien_coi_1997所示(。

(从我的评论中复制,因为这可能会有所帮助(

textarea替换input元素可能会产生糟糕的用户体验。为什么不从一开始就使用textarea呢?如果您希望样式基于输入长度而改变,例如,如果存在>20个字符,然后您可以使用CSS来完成此操作。

<script setup>
const props = defineProps({
modelValue: String,
})
</script>
<template>
<textarea
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
:rows="1"
:style="modelValue.length > 20 ? { minHeight: '100px' } : { minHeight: '0px' }"
/>
</template>
<AutoFocusedInput v-model="myString" />

演示(从@tony19派生(

最新更新