实现@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]*" 配合软键盘优化。

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

相关推荐
Captaincc2 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师3 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen4 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒4 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow5 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8185 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800785 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明5 小时前
第 6 章 组件进阶
前端·vue.js
江华森5 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端
南青5 小时前
Vue 3 中后台实战:我踩过的 10 个坑和最佳实践
前端