JavaScript限制文本框只允许输入数字(含小数与长度控制)
在使用表单或输入框时,往往需要限制用户仅能输入数字。传统的 keyCode 简单过滤存在体验缺陷,而第三方插件配置较为笨重。本文提供一段基于原生 JavaScript 的实现方案,支持自定义整数和小数长度,并通过处理光标位置与特殊按键来提升交互体验。
需求分析与传统方法的局限
在 Web 开发中,限制文本框只允许输入数字是常见的需求。过去常采用的简单方法是直接在 onkeydown 事件中判断 event.keyCode:
<input onkeydown="return event.keyCode>=48&&event.keyCode<=57||event.keyCode>=96&&event.keyCode<=105" />这种方法虽然简洁,但存在明显不足:它忽略了 Backspace、Delete、方向键、Home/End 等必要编辑键的操作,导致用户难以修改输入内容。此外,对于小数位的控制非常薄弱。
另一种选择是使用 jQuery 插件(如 Masked Input 或 MeioMask),它们功能强大且灵活,但在精细控制输入长度(特别是独立控制整数和小数位长度)时,往往缺乏足够的灵活性或配置过于复杂。
核心实现逻辑
为了实现更健壮的控制,我们需要构建一个自定义函数 validateDigitsOnly。该函数的核心在于区分不同场景下的按键行为,并实时计算当前输入值是否超出预设的长度限制。
第1步:定义全局配置参数
为了方便复用,我们利用 HTML 元素的数据属性来动态设置规则:
data-numbers:控制整数的最大长度(默认值为 15)。data-decimals:控制小数的最大长度(默认值为 2)。
第2步:处理特殊按键与组合键
首先拦截不影响数值性质的操作,确保用户可以自由编辑文本:
- 编辑类按键:包括退格 (
key == 8)、制表符 (key == 9)、回车 (key == 13)、ESC (key == 27)、删除 (key == 46)。 - 快捷键:Ctrl + A (全选)。
- 导航类按键:Home、End 以及上下左右四个方向键。
如果按下的是上述任一按键,直接返回,不阻止默认行为。同时,屏蔽 Shift、Alt 或 Ctrl 的非组合按键,防止触发非法字符输入。
第3步:获取当前状态与光标位置
在允许常规输入前,必须明确三个关键变量:
- 光标范围:通过封装
caret()函数获取光标的起始 (begin) 和结束 (end) 索引。这对于处理选中后粘贴或覆盖输入至关重要。 - 小数点位置:
val.indexOf(".")用于定位当前字符串中小数点的位置。 - 相对位置判断:判断光标是在小数点左侧还是右侧,以便分别校验整数部分和小数部分的长度。
第4步:执行严格的合法性校验
校验逻辑分为两部分:
- 数字输入校验:当按键为 0-9 (keyCode 48-57 或 96-105) 时,调用
validateValue函数。该函数检查:- 若无小数点,总长度是否超过
data-numbers。 - 若光标在小数点左侧,整数部分长度是否超限。
- 若光标在小数点右侧,剩余可输入的小数位是否达到上限。
- 若无小数点,总长度是否超过
- 小数符号校验:当按键为 " . " (keyCode 190 或 110) 时:
- 如果尚未输入过小数点,且后续空间足够,则允许输入。
- 如果已存在小数点,且当前选中的区域包含小数点(即准备替换已有小数点),则允许输入。
function validateDigitsOnly(evt) { var e = evt || window.event, key = e.keyCode || e.which; // 1. 放行编辑键 if (key == 8 || key == 9 || key == 13 || key == 27 || key == 46 || (key == 65 && event.ctrlKey === true) || (key >= 35 && key <= 40)) { return; } // 屏蔽修饰键 if (e.shiftKey || e.altKey || e.ctrlKey) { return false; } var el = e.target || e.srcElement, nl = parseInt(el.getAttribute("data-numbers") || 15), dl = parseInt(el.getAttribute("data-decimals") || 2), val = el.value, dotIndex = val.indexOf("."), rng = caret.call(el), rLeft = rng.end <= dotIndex, rRight = rng.begin > dotIndex; // 2. 处理数字输入 if ((key >= 48 && key <= 57) || (key >= 96 && key <= 105)) { if (validateValue(dotIndex, val, rLeft, rRight, nl, dl)) return; // 如果是覆盖选中部分的情况,需重新计算 val = val.substring(0, rng.begin) + val.substring(rng.end); dotIndex = val.indexOf("."); if (validateValue(dotIndex, val, rLeft, rRight, nl, dl)) return; } // 3. 处理小数点输入 else if ((key == 190 || key == 110) && dl > 0) { // 未输入过且空间足够,或者选区包含小数点则允许 if (dotIndex == -1 && (rng.end == val.length || val.substring(rng.end).length <= dl) || (dotIndex > -1 && rng.begin <= dotIndex && dotIndex < rng.end)) { return; } } return false; }第5步:辅助函数定义
验证值长度函数 validateValue:
function validateValue(dotIndex, val, rLeft, rRight, nl, dl) { // 无小数点时的总长度检查 if (dotIndex == -1 && val.length < nl) return true; // 光标在小数点左侧时检查整数长度 if (rLeft && val.substring(0, dotIndex).length < nl) return true; // 光标在小数点右侧时检查小数长度 if (rRight && val.substring(dotIndex + 1).length < dl) return true; return false; }光标位置获取函数 caret:
// 闭包形式暴露 caret 对象给 input 元素 function caret() { var begin, end; if (this.setSelectionRange) { begin = this.selectionStart; end = this.selectionEnd; } else if (document.selection && document.selection.createRange) { var range = document.selection.createRange(); begin = 0 - range.duplicate().moveStart('character', -100000); end = begin + range.text.length; } return { begin: begin, end: end }; }实际应用场景
根据项目需求,可以通过以下方式挂载该验证器:
方式一:原生 DOM 绑定
适用于不使用框架的基础页面:
<input type="text" id="t1" /> <input type="text" id="t2" data-numbers="5" data-decimals="4" /> <script> document.getElementById("t1").onkeydown = validateDigitsOnly; document.getElementById("t2").onkeydown = validateDigitsOnly; </script>方式二:HTML 内联绑定
适用于快速原型或简单组件:
<input type="text" onkeydown="return validateDigitsOnly(event)" />方式三:jQuery 批量绑定
如果使用 jQuery,可以更优雅地应用到多个元素:
<input type="text" class="digitsOnly" data-numbers="10" data-decimals="2" /> <script> $(".digitsOnly").keydown(validateDigitsOnly); </script>注意事项与边界情况
虽然 onkeydown
- 鼠标右键粘贴:用户通过右键菜单或菜单栏进行粘贴时,不会触发
onkeydown事件。建议配合表单验证库(如 jQuery Validate)或在onblur/oninput事件中增加后置校验。 - 拖拽输入:从网页其他位置选中文字拖入文本框,或通过鼠标拖拽选中框内文字时,同样可能绕过键盘事件。对于高安全性要求的应用,必须在前端提交前或后端接口层进行最终数据的强类型校验。
以上就是通过 JavaScript 限制文本框只允许输入数字及特定长度的详细内容,更多关于前端表单校验与数据格式控制的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













