VueJS中@input仅失焦触发,需改为输入时实时触发的解决方案
解决Vue中@input事件未实时触发的问题
你的问题核心是绑定的@input事件没有在用户输入过程中实时触发,反而仅在失焦时执行,这是因为你在ValidateInput函数中直接修改了v-model绑定的inputValue,导致Vue重新渲染输入框DOM,打断了@input事件的连续触发逻辑。
以下是两种可行的解决方案:
方案一:使用@input事件参数获取输入值
直接通过事件对象获取当前输入框的原始值,处理后再赋值给inputValue,避免v-model的即时更新冲突:
修改模板
<input v-model="inputValue" type="text" :placeholder="placeholder" :class="['w-full !border-none !focus:border-none p-2.5 shadow-none', disabled ? 'text-[#969c9f]' : 'black']" @input="ValidateInput($event)" :disabled="disabled" />
修改ValidateInput函数
ValidateInput(event) { let value = event.target.value; if (!value) { this.inputValue = null; this.$emit('update:modelValue', null); return; } switch(this.valueType) { case "Number": value = value.replace(/[^0-9]/g, ''); break; case "SP": value = value.replace(/^0+/, '').replace(/\D/g, ''); break; case "Number_with_TS": value = value.replace(/[^0-9]/g, ''); value = value.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); break; case "SP_with_TS": value = value.replace(/^0+/, '').replace(/\D/g, ''); value = value.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); break; case "decimal": value = value.replace(/[^0-9.]/g, ''); const parts = value.split('.'); if (parts.length > 2) { value = parts[0] + '.' + parts.slice(1).join(''); } break; case "ZipCode": value = value.replace(/[^0-9]/g, ''); if (value.length > 4) { value = value.substring(0, 4); } break; case "disabled": value = 0; break; case "model_spec": if (value.length > 60) { value = value.substring(0, 60); } break; case "cylinder_volume": value = value.replace(/[^\d,.]/g, ''); break; } this.inputValue = value === "" ? null : value; this.$emit('update:modelValue', this.inputValue); }
方案二:使用watch监听inputValue变化
通过Vue的watch选项监听inputValue的每一次变化,不管是用户输入还是代码修改,都会实时触发验证逻辑:
添加watch配置
export default { // ...其他组件选项 watch: { inputValue(newVal) { this.ValidateInput(newVal); } }, methods: { ValidateInput(value) { if (!value) { this.inputValue = null; this.$emit('update:modelValue', null); return; } let processedValue = value; switch(this.valueType) { case "Number": processedValue = processedValue.replace(/[^0-9]/g, ''); break; case "SP": processedValue = processedValue.replace(/^0+/, '').replace(/\D/g, ''); break; case "Number_with_TS": processedValue = processedValue.replace(/[^0-9]/g, ''); processedValue = processedValue.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); break; case "SP_with_TS": processedValue = processedValue.replace(/^0+/, '').replace(/\D/g, ''); processedValue = processedValue.replace(/\B(?=(\d{3})+(?!\d))/g, ' '); break; case "decimal": processedValue = processedValue.replace(/[^0-9.]/g, ''); const parts = processedValue.split('.'); if (parts.length > 2) { processedValue = parts[0] + '.' + parts.slice(1).join(''); } break; case "ZipCode": processedValue = processedValue.replace(/[^0-9]/g, ''); if (processedValue.length > 4) { processedValue = processedValue.substring(0, 4); } break; case "disabled": processedValue = 0; break; case "model_spec": if (processedValue.length > 60) { processedValue = processedValue.substring(0, 60); } break; case "cylinder_volume": processedValue = processedValue.replace(/[^\d,.]/g, ''); break; } processedValue = processedValue === "" ? null : processedValue; // 避免无限循环:仅当处理后的值与原value不同时才更新 if (processedValue !== value) { this.inputValue = processedValue; this.$emit('update:modelValue', processedValue); } } } }
模板调整
此方案下可以保留@input="ValidateInput",也可以直接移除,因为watch已经会自动监听inputValue的变化。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

