实现@imput支持用户输入最多三位整数,最多一位小数的数值

实现@imput支持用户输入最多三位整数,最多一位小数的数值

template 模板视图

html 复制代码
<template>
  <div>
    <label for="work-hours">工时:</label>
    <input
      id="work-hours"
      v-model="hours"
      type="text"
      placeholder="请输入工时(如:8.5)"
      @input="handleInput"
      @blur="handleBlur"
    />
    <p>当前值:{{ hours }}</p>
  </div>
</template>

script 脚本部分

js 复制代码
import { ref } from 'vue'

// 使用字符串类型以便更好地控制输入
const hours = ref('')

// 处理输入事件
const handleInput = (event) => {
  let value = event.target.value

  // 只允许数字和一个小数点
  const regex = /^\d{0,3}(.\d{0,1})?$/
  if (regex.test(value) || value === '') {
    hours.value = value
  } else {
    // 如果不符合规则,则截取到符合的部分
    const cleaned = cleanInput(value)
    hours.value = cleaned
    // 可选:同步 DOM 值(防止视图不更新)
    event.target.value = cleaned
  }
}

// 辅助函数:清理非法输入
const cleanInput = (value) => {
  // 移除非数字和非小数点字符(保留第一个小数点)
  let cleaned = ''
  let decimalFound = false

  for (let char of value) {
    if (/\d/.test(char)) {
      // 检查是否超过三位整数部分
      const parts = cleaned.split('.')
      if (!decimalFound && parts[0].length >= 3) continue // 整数部分超限
      if (decimalFound && parts.length > 1 && parts[1].length >= 1) continue // 小数部分超限
      cleaned += char
    } else if (char === '.' && !decimalFound) {
      decimalFound = true
      const parts = cleaned.split('.')
      if (parts[0] === '') cleaned = '0' // 自动补零,如 .5 -> 0.5
      cleaned += '.'
    }
    // 忽略其他字符
  }

  return cleaned
}

// 失焦时格式化最终值
const handleBlur = () => {
  let val = hours.value

  if (val === '.') {
    hours.value = ''
    return
  }

  // 去掉开头的多余 0,比如 007 -> 7
  if (val.startsWith('0') && val !== '0' && !val.startsWith('0.')) {
    const trimmed = val.replace(/^0+/, '')
    hours.value = trimmed ? parseFloat(trimmed).toFixed(1).replace(/.?0+$/, '') : '0'
  }

  // 格式化显示(可选)
  if (val.includes('.')) {
    const [int, dec] = val.split('.')
    hours.value = `${int}.${dec.slice(0, 1)}`
  }
}

AI 生成

在 Vue 中,要实现一个输入框(<input>)来限制用户只能输入最多三位整数位和最多一位小数位 的数值(即最大值为 999.9),可以通过多种方式实现。以下是一个完整的解决方案,使用 Vue 3 的 Composition API 和 <script setup> 语法:

✅ 需求分析

  • 允许输入:0, 12, 123, 123.4, .5 等。
  • 不允许:
    • 超过三位整数:如 1234
    • 超过一位小数:如 12.34
    • 非数字字符(除小数点外)
  • 实时校验并修正输入

✅ 示例代码(Vue 3 + Composition API)

vue 复制代码
<template>
  <div>
    <label for="work-hours">工时:</label>
    <input
      id="work-hours"
      v-model="hours"
      type="text"
      placeholder="请输入工时(如:8.5)"
      @input="handleInput"
      @blur="handleBlur"
    />
    <p>当前值:{{ hours }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

// 使用字符串类型以便更好地控制输入
const hours = ref('')

// 处理输入事件
const handleInput = (event) => {
  let value = event.target.value

  // 只允许数字和一个小数点
  const regex = /^\d{0,3}(\.\d{0,1})?$/
  if (regex.test(value) || value === '') {
    hours.value = value
  } else {
    // 如果不符合规则,则截取到符合的部分
    const cleaned = cleanInput(value)
    hours.value = cleaned
    // 可选:同步 DOM 值(防止视图不更新)
    event.target.value = cleaned
  }
}

// 辅助函数:清理非法输入
const cleanInput = (value) => {
  // 移除非数字和非小数点字符(保留第一个小数点)
  let cleaned = ''
  let decimalFound = false

  for (let char of value) {
    if (/\d/.test(char)) {
      // 检查是否超过三位整数部分
      const parts = cleaned.split('.')
      if (!decimalFound && parts[0].length >= 3) continue // 整数部分超限
      if (decimalFound && parts.length > 1 && parts[1].length >= 1) continue // 小数部分超限
      cleaned += char
    } else if (char === '.' && !decimalFound) {
      decimalFound = true
      const parts = cleaned.split('.')
      if (parts[0] === '') cleaned = '0' // 自动补零,如 .5 -> 0.5
      cleaned += '.'
    }
    // 忽略其他字符
  }

  return cleaned
}

// 失焦时格式化最终值
const handleBlur = () => {
  let val = hours.value

  if (val === '.') {
    hours.value = ''
    return
  }

  // 去掉开头的多余 0,比如 007 -> 7
  if (val.startsWith('0') && val !== '0' && !val.startsWith('0.')) {
    const trimmed = val.replace(/^0+/, '')
    hours.value = trimmed ? parseFloat(trimmed).toFixed(1).replace(/\.?0+$/, '') : '0'
  }

  // 格式化显示(可选)
  if (val.includes('.')) {
    const [int, dec] = val.split('.')
    hours.value = `${int}.${dec.slice(0, 1)}`
  }
}
</script>

<style scoped>
input {
  padding: 8px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
}
</style>

🔍 功能说明

特性 说明
v-model 绑定字符串 更容易处理中间状态(如正在输入 .5
正则 /^\d{0,3}(\.\d{0,1})?$/ 保证不超过 3 位整数、1 位小数
@input 实时过滤 防止非法字符或超出长度输入
cleanInput() 函数 手动解析字符串,精确控制每一位输入
@blur 处理 输入完成时进行规范化

✅ 支持的输入示例

用户输入 实际结果 说明
1 1 ✅ 正常
123 123 ✅ 最大整数
123.4 123.4 ✅ 合法小数
123.45 123.4 ❌ 第二位小数被截断
1234 123 ❌ 第四位整数被忽略
.5 0.5 ⚠️ 可自动补 0 或保留 .5(本例中保留)
abc12.3xyz 12.3 ✅ 非法字符被过滤

💡 进阶建议

  • 若用于表单提交,建议在提交前再次校验 parseFloat(hours.value) 是否在 0 ~ 999.9 范围内。
  • 可改为 type="number" 并配合 step="0.1",但对输入控制较弱,仍需 JS 辅助。
  • 移动端可考虑使用 pattern="[0-9]*" 配合软键盘优化。

这个方案可以确保用户只能输入合法的工时数据,适合用于填报系统、考勤系统等场景。

相关推荐
明天好,会的11 小时前
分形生成实验(五):人机协同破局--30万token揭示Actix-web状态管理的微妙边界
运维·服务器·前端
C_心欲无痕11 小时前
nginx - alias 和 root 的区别详解
运维·前端·nginx
我是苏苏13 小时前
Web开发:C#通过ProcessStartInfo动态调用执行Python脚本
java·服务器·前端
无羡仙14 小时前
Vue插槽
前端·vue.js
用户63879947730515 小时前
每组件(Per-Component)与集中式(Centralized)i18n
前端·javascript
SsunmdayKT15 小时前
React + Ts eslint配置
前端
开始学java15 小时前
useEffect 空依赖 + 定时器 = 闭包陷阱?count 永远停在 1 的坑我踩透了
前端
zerosrat15 小时前
从零实现 React Native(2): 跨平台支持
前端·react native
狗哥哥15 小时前
🔥 Vue 3 项目深度优化之旅:从 787KB 到极致性能
前端·vue.js