JavaScript限制文本框只允许输入数字的方法对比与实现
本文对比了限制文本框仅允许输入数字的几种常见方法,包括原生onkeydown事件、jQuery Masked Input及MeioMask插件。针对现有方案在操作体验和长度控制上的不足,提供了一套基于onkeydown和自定义属性的完整JavaScript实现方案,支持通过data-numbers和data-decimals属性灵活控制整数与小数长度,并处理了光标位置、粘贴及特殊键位等边界情况。
限制文本框输入数字的方法对比
在许多开发场景中,我们需要限制用户只能在文本框中输入数字。尝试过多种现有方案后,发现它们往往存在局限性,因此决定自行实现一个更为完善的解决方案。
既往采用的技术手段
一种常见思路是利用onkeydown事件来拦截非数字按键。
具体代码实现如下:
<input onkeydown="return event.keyCode>=48&&event.keyCode<=57||event.keyCode>=96&&event.keyCode<=105" /> 此外,还可以借助jQuery插件Masked Input:http://digitalbush.com/projects/masked-input-plugin/
或者使用另一个jQuery插件MeioMask:https://github.com/fabiomcosta/jquery-meiomask
然而,单纯依靠onkeydown事件进行控制相对繁琐,上述简化版代码未涵盖所有功能键,导致操作体验较差。
虽然上述两个jQuery插件使用较为灵活,能满足大部分需求,但在控制输入长度方面显得不够灵活(或许是我未找到更灵活的使用方式?)。
实施细节
自定义数字输入验证实现
为了解决长度控制问题,我们可以借鉴maskedInput中的部分方法来提取光标位置。
同时,参考StackOverflow上提供的通用键盘敲击处理方法:http://stackoverflow.com/questions/469357/html-text-input-allow-only-numeric-input
更新说明:参考http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes上列出的keycode列表。
在此基础上,我们自定义两个属性来分别设置整数和小数的最大长度:
•data-numbers属性用于控制整数部分的输入长度。
•data-decimals属性用于控制小数部分的输入长度。
最终完整的代码实现如下:
具体函数代码如下:
function validateDigitsOnly(evt) {
var e = evt || window.event,
key = e.keyCode || e.which;
if (
// 允许退格、Tab、回车、Esc、删除键
key == 8 || key == 9 || key == 13 || key == 27 || key == 46 ||
// 允许Ctrl + A全选
(key == 65 && event.ctrlKey === true) ||
// 允许Home, End及四个方向键
key >= 35 && key <= 40) {
return;
}
if (e.shiftKey || e.altKey || e.ctrlKey) {
return false;
}
var el = e.target || e.srcElement,
// 获取整数最大长度
nl = el.getAttribute("data-numbers") || 15,
// 获取小数最大长度
dl = el.getAttribute("data-decimals") || 2,
val = el.value,
// 获取小数点位置
dotIndex = val.indexOf("."),
rng = caret.call(el),
// 判断光标是否在小数点左侧
rLeft = rng.end <= dotIndex,
// 判断光标是否在小数点右侧
rRight = rng.begin > dotIndex;
if (
// 允许0-9数字键
key >= 48 && key <= 57 ||
// 允许小键盘0-9数字键
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;
}
else if (
// ".", ","
(key == 190 /*|| key == 188*/ ||
// 允许小键盘上的 ".", ","键
key == 110/*|| key == 109*/) &&
// 仅当允许输入小数时
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;
}
// 验证输入值是否合法
function validateValue(dotIndex, val, rLeft, rRight, nl, dl) {
if (
// 未输入小数点且总长度未超整数上限
dotIndex == -1 && val.length < nl ||
// 光标在小数点前且整数部分长度未超上限
rLeft && val.substring(0, dotIndex).length < nl ||
// 光标在小数点后且小数部分长度未超上限
rRight && val.substring(dotIndex + 1).length < dl)
return true;
return false;
}
// 获取光标选中范围
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 };
} 调用方式
代码使用示例
具体使用方法如下:
HTML代码如下:
<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标签中编写:
HTML代码如下:
<input type="text" id="lwme_text_3" onkeydown="return validateDigitsOnly(event)" /> 如果项目中引入了jQuery,使用方式将更加简洁:
HTML代码如下:
<input type="text" class="digitsOnly" /> JavaScript代码如下:
$(".digitsOnly").keydown(validateDigitsOnly); 总结
注意事项与补充说明
该方法在某些情况下效率可能不够高,且未处理所有键盘按键,不排除特定环境下失效的可能,但对于大多数常规使用场景已足够。
如有额外需求,请自行修改代码;若有更优方案,欢迎分享(*^__^*)
over
PS:01.18更新了一些keyCode的判断,以及错把110写成109≡(▔﹏▔)≡
补充说明:针对通过右键菜单或菜单栏执行粘贴操作的情况,需进行特殊处理;
另一种极端场景:在网页界面中选取文本并拖拽至输入框,或在输入框内选取文本进行拖拽,此类操作均需额外处理
对于以上两种需要额外处理的情况,比较便捷的方法是加一个验证,比如jQuery.validate之类的表单验证,否则处理起来比较麻烦
再PS:在win8下,切换到微软拼音可能会造成无法输入,不知道其他系统或者其他输入法有没有这个问题( *_*) (`~~`) ====
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
