Vue3输入组件事件异常:清空后重输入首字符丢失问题
问题分析与解决方案
问题根源
你的输入组件绑定了:value="props.modelValue",但仅在@change事件中触发update:modelValue更新父组件的绑定值,而@input事件只执行验证逻辑,没有同步更新modelValue。这就导致:
- 清空输入框后,父组件的
modelValue是空字符串 - 输入首字符时,
input事件触发验证,但父组件的modelValue未更新,输入框的value仍保持为空,所以首字符无法显示 - 输入第二个字符时,虽然
modelValue还是旧值,但输入框的DOM值已经变化,后续渲染才逐步跟上,出现延迟更新的现象
修复方案
需要在input事件触发时,同时完成值更新和验证逻辑,确保组件的value和父组件的modelValue实时同步。
修改后的组件代码如下:
<template> <div class="form-group"> <label :for="props.id || `${props.name}Input`" class="form-label" :class="{ 'form-label--required': props.required }" v-if="props.label" > {{ props.label }} </label> <input class="form-control mb-2" type="text" v-bind="$attrs" :id="props.id || `${props.name}Input`" :placeholder="props.label" :name="props.name" :required="props.required" :min="props.min" :max="props.max" :value="props.modelValue" :class="{ 'is-invalid': !!errorMessage, }" @input="handleInput" /> <div class="invalid-feedback mb-3" v-if="!!errorMessage"> {{ errorMessage }} </div> </div> </template> <script lang="ts"> export default { inheritAttrs: false, }; </script> <script lang="ts" setup> import { computed, defineEmits, defineProps, reactive } from 'vue'; const props = defineProps({ label: { type: String, }, name: { type: String, required: true, }, required: { type: Boolean, default: false, }, validationMessage: { type: String, required: false, }, modelValue: { type: String, default: '', }, id: { type: String, required: false, }, min: { type: [String, null, undefined], default: null, }, max: { type: [String, null, undefined], default: null, }, }); const emits = defineEmits(['update:modelValue', 'isValid']); const validation = reactive({ isValid: false, message: '', }); const errorMessage = computed(() => { return Array.isArray(props.validationMessage) ? props.validationMessage[0] : props.validationMessage || validation.message; }); // 合并值更新与验证逻辑 const handleInput = (event: Event) => { const target = event.target as HTMLInputElement; // 先更新modelValue,确保输入框值与父组件同步 emits('update:modelValue', target.value); if (props.required) { if (target.value) { validation.isValid = true; validation.message = ''; } else { validation.isValid = false; validation.message = 'This field is required.'; } emits('isValid', validation.isValid); } }; </script>
关键修改点
- 新增
handleInput函数,将@input事件绑定到该函数 - 在
handleInput中先触发update:modelValue更新父组件的绑定值,再执行验证逻辑 - 移除原
@change事件(因为input事件已经实时处理值更新,change事件会冗余)
这样修改后,输入框的内容会实时同步到父组件的modelValue,清空后重新输入首字符时,组件的value会立即更新,不会出现首字符不显示的问题。
内容的提问来源于stack exchange,提问作者mcmac
相关产品推荐
相关产品推荐

