简体   繁体   English

如何将焦点设置在新(自动)呈现的 dom 元素上?

[英]How can i set focus on a newly (automatically) rendered dom element?

I have an input field that gets replaced automatically with a textarea and same content depending on the number of characters the user has entered:我有一个输入字段,它会根据用户输入的字符数自动替换为文本区域和相同的内容:

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

The problem i have is that the focus gets lost when a user enters the 21st character.我遇到的问题是,当用户输入第 21 个字符时,焦点会丢失。 And thus the user gets irritated because when he types the 22nd character it does not appear in the textarea (no focus).因此用户会感到恼火,因为当他键入第 22 个字符时,它不会出现在文本区域中(无焦点)。 How can i set the focus on the newly rendered textarea then?那么我怎样才能将焦点设置在新呈现的文本区域上呢? Problem here is that it gets rendered automatically.这里的问题是它会自动呈现。 Otherwise i could set a ref on the textarea and call focus().否则我可以在 textarea 上设置一个 ref 并调用 focus()。

Another issue is the removal of the 21st character and the switch-back from textarea to the input elment.另一个问题是第 21 个字符的删除以及从文本区域切换回输入元素。

You could wrap the textarea / input in a component, and use its mounted hook to call its focus() , as seen in this component:您可以将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" />

demo 演示

While this is technically possible, this UX is probably not ideal, and you should consider other designs that don't require focusing input like this (as indicated by @kien_coi_1997).虽然这在技术上是可行的,但这种 UX 可能并不理想,您应该考虑其他不需要像这样的聚焦输入的设计(如 @kien_coi_1997 所示)。

(copy from my comment because this might be helpful) (从我的评论中复制,因为这可能会有所帮助)

Replacing an input element by a textarea is likely to create a horrible UX.textarea替换input元素可能会产生糟糕的用户体验。 Why don't you just use textarea from the beginning?你为什么不从一开始就使用textarea If you want the style to change based on the input length, eg increase the height if there are > 20 characters, then you can use CSS to do that.如果您希望根据输入的长度更改样式,例如,如果有 > 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" />

demo (forked from @tony19) 演示(从@tony19 分叉)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM