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

如何在Vuetify 3中实现支持输入小数点的小数输入框?

在Vuetify 3中实现支持小数输入的自定义数字输入框

问题出在使用type="number"的v-text-field时,浏览器会自动将不完整的数字输入(比如单独的.或123.)转换为NaN,导致无法正常更新绑定值。下面是直接可用的解决方案:

完整组件代码

<template>
  <v-text-field 
    v-model="inputValue" 
    type="text" 
    :label="label" 
    outlined 
    @input="processInput"
  />
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

const props = defineProps<{
  label: string;
  modelValue: number | null;
}>();

const emit = defineEmits(["update:modelValue"]);

// 用内部ref保存输入的字符串,处理中间输入状态
const inputValue = ref(props.modelValue?.toString() || "");

// 监听父组件值变化,同步到输入框
watch(
  () => props.modelValue,
  (newVal) => {
    inputValue.value = newVal?.toString() || "";
  }
);

const processInput = () => {
  // 过滤掉非数字和小数点的非法字符
  let filtered = inputValue.value.replace(/[^0-9.]/g, "");
  
  // 确保输入中只有一个小数点
  const dotParts = filtered.split(".");
  if (dotParts.length > 2) {
    filtered = dotParts[0] + "." + dotParts.slice(1).join("");
  }
  
  // 更新输入框为过滤后的合法内容
  inputValue.value = filtered;
  
  // 转换为合法数字输出
  let outputValue: number | null = null;
  if (filtered === "") {
    outputValue = null;
  } else if (filtered === ".") {
    outputValue = 0;
  } else {
    outputValue = Number(filtered);
  }
  
  emit("update:modelValue", outputValue);
};
</script>

关键逻辑说明

  1. 改用text类型输入框:避免浏览器自动处理数字输入导致的NaN问题,手动控制输入内容。
  2. 输入内容过滤:通过正则表达式只保留数字和小数点,同时限制只能输入一个小数点,防止出现123..45这类非法格式。
  3. 中间状态处理:支持输入过程中的临时状态(比如单独的.),将其转换为0或null,确保父组件始终收到合法值。
  4. 双向同步:监听父组件传来的modelValue,确保外部更新时输入框内容同步变化。

可选调整:强制输出数字类型

如果不需要null状态,希望父组件始终收到数字值,可以修改processInput中的输出逻辑:

let outputValue: number = 0;
if (filtered !== "" && filtered !== ".") {
  outputValue = Number(filtered);
}

同时更新props类型:

const props = defineProps<{
  label: string;
  modelValue: number;
}>();

内容的提问来源于stack exchange,提问作者JoachimR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:10:29