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

如何用Vuetify创建支持整数限制的数字输入组件?

Vuetify数字输入组件开发问题

需求

  • 输入输出值支持undefined或null(清空字段时不返回0)
  • 组件尽量隐藏增减按钮
  • 当isAcceptingFloatingPointNumbers = false时,仅允许输入整数,禁止浮点数输入

初始实现代码

<template>
  <v-app>
    <v-main>
      <v-text-field 
        type="number"
        label="number input" 
        :clearable="true"
        :model-value="num"
        @update:modelValue="num = $event"
      />
    </v-main>
  </v-app>
</template>

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

const num: Ref<unknown> = ref(undefined)

watch(num, () => console.log(num.value))
</script>

现有问题

曾尝试添加自定义校验规则:

v => Number.isInteger(v) || 'Must be integer'

但该规则会在值为undefined时触发提示,因此希望直接阻止非法输入而非事后校验。

基于参考实现了按键过滤逻辑,但当前过滤函数存在漏洞:当isAcceptingFloatingPointNumbers = false时,仍能输入12.4——因为拼接字符串转数字时会忽略小数点,将12.4识别为124,导致无法正确拦截小数点输入。

当前组件代码

NumberField.vue

<template>
  <v-text-field 
    type="number"
    label="number input" 
    :clearable="true"
    :model-value="num"
    @update:modelValue="emit('update:modelValue', $event)"
    @keypress="filterInput"
  />
</template>

<script setup lang="ts">
const props = defineProps<{
  num: unknown;
  isAcceptingFloatingPointNumbers: boolean;
}>();

const emit = defineEmits<{
  (e: "update:modelValue", newValue: unknown): void;
}>();

function filterInput(inputEvent) {
  if(props.isAcceptingFloatingPointNumbers.value) {
    return true;
  }
  
  const inputAsString = inputEvent.target.value.toString() + inputEvent.key.toString();
  const inputValue = Number(inputAsString);
  
  if(!Number.isInteger(inputValue)) {
    inputEvent.preventDefault();
  }
  
  return true;
}
</script>

消费组件代码

<template>
  <number-field :num="num" :isAcceptingFloatingPointNumbers="false" @update:model-value="num = $event" />
</template>

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

const num: Ref<unknown> = ref(undefined);
  
watch(num, () => console.log(num.value));
</script>

修复方案

问题核心在于原过滤逻辑通过拼接字符串转数字的方式判断合法性,会自动忽略小数点导致误判。正确做法是直接校验输入按键的合法性,同时处理控制键(退格、方向键等)的允许逻辑,再配合样式隐藏增减按钮、值同步处理确保清空时返回undefined。

最终完整NumberField.vue代码

<template>
  <v-text-field 
    type="number"
    label="number input" 
    :clearable="true"
    :model-value="num"
    @update:modelValue="handleUpdate"
    @keypress="filterInput"
    class="no-spin-buttons"
  />
</template>

<script setup lang="ts">
import type { KeyboardEvent } from 'vue';

const props = defineProps<{
  num: number | undefined | null;
  isAcceptingFloatingPointNumbers: boolean;
}>();

const emit = defineEmits<{
  (e: "update:modelValue", newValue: number | undefined | null): void;
}>();

// 处理值更新,清空时返回undefined
function handleUpdate(value: unknown) {
  const newValue = value === '' ? undefined : value;
  emit('update:modelValue', newValue as number | undefined | null);
}

// 按键过滤逻辑
function filterInput(inputEvent: KeyboardEvent) {
  const { key } = inputEvent;
  // 允许控制键(退格、删除、方向键等)
  if (inputEvent.ctrlKey || inputEvent.metaKey || inputEvent.key.length !== 1) {
    return true;
  }

  if (!props.isAcceptingFloatingPointNumbers) {
    // 整数模式:仅允许数字键(0-9)
    if (!/^\d$/.test(key)) {
      inputEvent.preventDefault();
      return false;
    }
  } else {
    // 浮点数模式:允许数字和单个小数点
    if (!/^\d$/.test(key) && key !== '.') {
      inputEvent.preventDefault();
      return false;
    }
    const currentValue = (inputEvent.target as HTMLInputElement).value;
    // 已有小数点时禁止再输入
    if (key === '.' && currentValue.includes('.')) {
      inputEvent.preventDefault();
      return false;
    }
  }
  return true;
}
</script>

<style scoped>
/* 隐藏数字输入框的增减按钮 */
.no-spin-buttons input[type="number"]::-webkit-outer-spin-button,
.no-spin-buttons input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.no-spin-buttons input[type="number"] {
  -moz-appearance: textfield;
}
</style>

修复效果说明

  1. 整数模式下直接拦截非数字按键,彻底禁止小数点输入
  2. 通过CSS隐藏了数字输入框的增减按钮
  3. 清空字段时自动返回undefined,符合需求
  4. 浮点数模式下限制仅能输入一个小数点,避免非法格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:01:56