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

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

相关推荐
RoyLin2 小时前
TypeScript设计模式:状态模式
前端·后端·typescript
RoyLin2 小时前
TypeScript设计模式:观察者模式
前端·后端·typescript
干就完了12 小时前
js对象常用方法都在这,使用时想不到?不存在的
前端·javascript
艾小码2 小时前
还在硬邦邦跳转页面?Vue这3招让应用丝滑如德芙!
前端·javascript·vue.js
RoyLin2 小时前
TypeScript设计模式:备忘录模式
前端·后端·typescript
阿笑带你学前端2 小时前
Flutter本地通知系统:记账提醒的深度实现
前端·flutter
RoyLin2 小时前
TypeScript设计模式:仲裁者模式
前端·后端·typescript
子兮曰2 小时前
🚀前端依赖配置避坑指南:深度解析package.json中devDependencies的常见误解
前端·javascript·npm
瑶琴AI前端2 小时前
【零成本高效编程】VS Code必装的5款免费AI插件,开发效率飙升!
前端·ai编程·visual studio code