You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:39:58