JavaScript限制文本框只允许输入数字的方法对比与实现

作者:小括号

时间:2026-10-26

浏览:318

本文对比了限制文本框仅允许输入数字的几种常见方法,包括原生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下,切换到微软拼音可能会造成无法输入,不知道其他系统或者其他输入法有没有这个问题( *_*) (`~~`) ====

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章