解决type=number的input可以输入+-e符号的情况

在前端开发中,当使用input[type=number]时,用户仍可能输入+-e等非数字字符。本文介绍了四种方法来解决这个问题:1) 值改变时替换非数字内容,但存在缺陷;2) 手动保存旧值并监听按键,避免值被立即清除;3) 使用键入事件拦截,作为最佳实践;4) 创建自定义输入标签以实现更精细的控制。通过这些方法,可以确保用户只能输入预期的数字内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在输入框input标签设置type="number"的目的就是为了规避用户输入数字以外的内容。然而,在html的w3c标准里,e认定为自然对数中的无理数常量,+-则是表示正负,生产中有时不需要甚至禁止输入这些。

1.值改变时,替换其中非数字内容(效果不好)

为输入框绑定事件,去除掉其中非数字和小数点部分。
onchange事件其实更接近于onblur,失焦且新旧值不等时才触发。oninput可做到输入单个字符就触发。

此外,网上还有使用onkeyup方法,监听按键抬起事件,除CtrlAltShiftEsc等键。(说关机键的请回炉重造。)
值得注意的是,onkeydown时value尚未改变,无法监听值并替换。

function setNum(e){
	e.value=e.value.replace(/[^0-9.]/g,"");
}

在各个方法中,输入+-e后,监听input的值,不论是e.value还是$(e).val(),打印出来都是空,而(不替换符号时)页面上有显示内容。
起初以为是jQuery或者项目中的其他插件的影响,后单独起一个demo,效果也是如此。

<input type="number" oninput="setNum(this)">
function setNum(e){
	console.log(e.value);
	// e.value = e.value.replace(/[^0-9.]/g,"");
}

inputDemo
不仅如此,小数点输入后仍然被触发清除,而焦点在最左边。
输入+-e后替换的也是整体而未保留数字。
输入1.后value=1,以上代码就会将其替换为1。
输入1e后value为空,会直接替换掉内容为空string。
所以,我不知道别人是怎么实现的,我这里行不通。
后来想想,估计是type=text吧,这样不仅没有原生的加减,图标点击加减功能,没有step属性,而且默认为文本输入,输入后闪现再消失,用户体验不好。

2.手动保存旧值,监听按键

如图,当我输入1.的时候,打印出来是1,其原生属性valueAsNumber=1我也能理解,为毛value=1,输入并显示e的时候,value=""valueAsNumber=NaN,你既然判断e为数字可以显示,真是当面一套背后一套。导致我没法从input的任何属性中找到其显示的内容,也就没法从value值判断是否输入+-e

value

于是想到了一个方法,在当前页面存储一个变量,记录该输入框的旧值,若按键是+-e则将value(此时value="")替换为旧值
注意触发onkeydownonkeyuponchangeoninput等方法的顺序及关系。而且监听按键的范围还不一样。
多个输入框则需要定义并寻找对应变量,所以我就给input定义两个自定义属性。

<input type="number" oninput="setNum(this)" onkeydown="downTest(this)" diyValue="" diyKey=false>
function setNum(e) {
    if (e.diyKey) {
        e.value = e.diyValue;
    } else {
        e.diyValue = e.value;
    }
}

function downTest(e) {
    console.log(event.keyCode);
    e.diyKey = event.keyCode === 69 || event.keyCode === 187 || event.keyCode === 189;
}

3.键入事件拦截(最优解)

监听键入事件keypress,区别于keydown事件,该事件不监听特殊键,如CtrlShift

document.getElementById("test").addEventListener('keypress', function (e) {
    let restricted = "+-e";
    let key = e.keyCode || e.which;
    for (let i = 0; i < restricted.length; i++) {
        if (restricted.charCodeAt(i) === key) {
            e.returnValue = false;
        }
    }
    return true;
});

4.自定义标签

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_custom_elements

class CustomInput extends HTMLInputElement {
    constructor() {
        super();
        this.addEventListener('input', this.handleInput.bind(this));
    }

    handleInput(event) {
        const val = event.target.value;
        this.value = val.replace(/\D/g, '');
    }
}

customElements.define('custom-input', CustomInput, {extends: 'input'});

使用:

<input is="custom-input"/>

其中custom-input对应customElements.define()的第一个参数,必须单词+-+单词严格命名。听说js其实有伪编译过程,class及define方法,可以不用在onload后触发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汤卓杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值