js 输入整数

博客提到使用 /^\\+?[1-9][0-9]*$/ 验证输入整数存在问题,小数也可输入,还给出了转载来源。主要围绕JavaScript中输入整数的正则表达式展开。

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

1.我用 /^\+?[1-9][0-9]*$/ 貌似不对(小数也可以输入)   

2.输入整数

 n = /^[1-9]\d*$/; 、

 

 

  var re = /^[0-9]\d*$/; //判断字符串是否为数字 
                if (!value) {
                    return callback(new Error('可得魔币不能为空'));
                }else if(!re.test(value)){
                    return callback(new Error('请输入整数'));
                }else  if(value<0) {
                      return callback(new Error('可得魔币不小于0'));
                }else {
                     callback();
                }

 

转载于:https://www.cnblogs.com/guangzhou11/p/10807616.html

<think>我们要求输入框只能输入整数(包括正整数、负整数和0) 注意:用户可能输入负号,所以不能简单地过滤掉所有非数字字符,需要允许负号(但只能出现在开头) 同时,不能出现多个负号,也不能在中间出现负号。 另外,我们可能还需要处理一些边界情况,比如只输入了负号没有数字,或者输入了多个负号等。 以下提供几种实现方式: 1. 使用HTML5 input type="number" 并设置step="1",但注意这允许输入小数,因为浏览器可能允许输入小数,但我们可以通过JS来限制。 2. 使用input type="text"并配合JS事件(如oninput)来过滤。 这里我们主要考虑第二种,因为type="number"在移动端会调起数字键盘,但在桌面端可能会有上下箭头,而且不同浏览器行为不一致。但是,我们也可以结合两者。 推荐方案:使用type="number"并设置step,然后通过JS确保输入的是整数。 但是,注意:type="number"允许输入小数点和e(科学计数法),所以我们需要额外处理。 另一种方案是使用type="text"并添加输入过滤。 下面我们分别给出示例: 方案一:使用type="text"并过滤 - 允许开头有一个负号,后面只能输入数字 - 如果用户删除了所有数字,那么负号也应该被删除(或者允许一个单独的负号?但这样不是整数,所以我们在输入过程中可以允许,但在失去焦点时修正) 实时过滤的代码: oninput="this.value=this.value.replace(/[^0-9\-]/g, '').replace(/(?!^)-/g, '').replace(/^(-)?-+/g, '$1')" 但是这样比较复杂,而且可能不够健壮。我们可以分步骤: - 首先,移除非数字和除第一个位置以外的负号 - 然后,处理多个负号的情况 更简单的方法:匹配整个字符串,只允许以负号开头(可选)后跟数字。 我们可以这样: oninput="this.value=this.value.replace(/[^0-9\-]/g, ''); // 先移除非数字和负号以外的字符 this.value=this.value.replace(/(?!^)-/g, ''); // 删除非开头的负号 this.value=this.value.replace(/^(-)?-+/g, '$1'); // 避免多个负号,只保留第一个(如果有) 但是,这样还是可能留下一个单独的负号,我们可以在失去焦点时处理,或者实时处理:如果只有一个负号,我们可以允许(因为用户可能正在输入),但最终提交时再检查。 方案二:使用type="number"并配合JS,在输入时去掉非整数部分。 考虑到易用性和移动端支持,我们可能更倾向于使用type="number",但需要处理小数点和e字符。 我们可以这样: <input type="number" step="1" oninput="this.value=this.value.includes('.') ? Math.floor(this.value) : this.value"> 但是,这样处理并不完美,因为用户可能输入小数点,我们立即将其转换为整数,但转换后用户看到的小数点会被删除,体验不好。 因此,我们推荐使用input type="text"并配合正则表达式过滤。 这里给出一个更健壮的过滤函数(只允许整数,包括负整数): function integerInput(input) { let value = input.value; // 先允许负号开头,后面是0个或多个数字 if (/^-?\d*$/.test(value)) { // 如果匹配,说明是合法输入,保留 return; } // 否则,将输入的值修正为上一次的合法值(或者过滤掉非法字符) // 我们可以尝试提取出合法部分:开头的负号(可选)后跟数字 let match = value.match(/^(-?\d*)/); if (match) { input.value = match[0]; } else { input.value = ''; } } 但是,我们也可以使用更简单的方法:直接替换掉非法字符,但保留开头的负号。 下面提供一个在input事件中过滤的通用函数: HTML: <input type="text" oninput="formatInteger(this)"> JS: function formatInteger(input) { let value = input.value; // 如果为空,则直接返回 if (value === '') return; // 先检查是否整个字符串符合整数格式(可选负号开头,后跟数字) // 但注意,用户可能正在输入,所以允许以负号开头且后面没有数字(比如只输入了一个负号) // 所以我们允许:负号开头(可选)后跟0个或多个数字 if (!/^-?\d*$/.test(value)) { // 如果不符合,则过滤:只保留开头的负号(如果有)和数字 // 先去掉开头的负号后面的所有非数字 let newValue = value.replace(/^(-)?[^\d]*(\d+)?.*$/, function(match, p1, p2) { // p1是开头的负号(如果有),p2是后面的数字(如果有) return (p1 || '') + (p2 || ''); }); // 但是上面的正则可能无法处理所有情况,我们换一种方式:提取出负号(如果出现在开头)和所有数字 // 更简单:直接替换掉所有非数字字符,但注意开头的负号要保留 // 所以,我们先把字符串分成两部分:开头的负号(如果有)和其余部分 let hasMinus = value[0] === '-'; let numPart = value.replace(/-/g, ''); // 先去掉所有负号 numPart = numPart.replace(/\D/g, ''); // 去掉非数字 input.value = hasMinus ? '-' + numPart : numPart; } } 但是这样处理,如果用户输入了多个负号,我们只保留第一个负号(因为开头的负号我们单独判断,然后后面的负号都被去掉了)?实际上,我们上面的做法是先去掉所有负号,然后再在开头加上负号(如果一开始有负号的话),这样会导致中间出现的负号被删除,但开头的负号保留,然后后面跟着数字。 但是,如果用户一开始没有负号,但中间输入了负号,那么负号会被删除,只留下数字。这样符合要求。 然而,这个函数有一个问题:如果用户把光标移到中间输入负号,那么负号会被删除,而且开头的负号状态会被保留(即使你删除了开头的负号,我们也会在开头加上负号?不对,我们判断的是value[0]是否是负号,所以如果用户删除了开头的负号,那么整个字符串就没有负号了,所以不会加负号)。 但是,这个函数在用户输入过程中会不断重置整个输入框的值,可能会导致光标位置错乱。所以,我们需要记录光标位置并在过滤后恢复。 因此,我们可能需要一个更简单的方案:只允许输入数字和开头的负号,并且开头的负号只能有一个。 下面提供一个更简单且体验较好的方法: function formatInteger(input) { // 获取当前光标位置 let start = input.selectionStart; let end = input.selectionEnd; let value = input.value; // 新值:只保留开头的负号(如果有)和数字 let newValue = value.replace(/-/g, ''); // 先去掉所有负号 // 如果原始字符串第一个字符是负号,那么我们在新值前面加上负号 if (value.charAt(0) === '-') { newValue = '-' + newValue; } // 更新输入框的值 input.value = newValue; // 调整光标位置 // 因为删除了非数字字符,光标位置需要调整 // 计算删除了多少个非数字字符(负号和非数字) let removed = value.length - newValue.length; // 如果删除的字符在光标之前,那么光标位置要前移 if (start > 0) { // 计算新光标位置 let newStart = start - removed; if (newStart < 0) newStart = 0; input.setSelectionRange(newStart, newStart); } else { input.setSelectionRange(start, end); } } 但是这个方法会改变光标位置,而且计算复杂。 因此,我们推荐一个更简洁的方法:使用正则表达式过滤,但只允许开头有一个负号,后面全是数字。 我们可以在每次输入时,将输入的值替换为:如果以负号开头,则后面只能有数字;否则,整个字符串只能有数字代码: function formatInteger(input) { input.value = input.value.replace(/[^0-9-]/g, '') // 移除非数字和负号以外的字符 .replace(/(?!^)-/g, '') // 将非开头的负号删除 .replace(/^(-)?(-*)/, (_, a, b) => a || ''); // 如果开头有负号,则保留一个,否则去掉所有负号 } 但是,第三个replace是为了处理多个开头的负号?比如"--123",经过第一个replace变成"--",第二个replace(非开头的负号)不会删除开头的负号,所以第三个replace:匹配开头(可能有负号a)和后面连续的负号b,然后替换为a(如果有)或空字符串(没有a的话)。这样,如果开头有多个负号,最终只会保留一个。 但是,这样处理还是不够完美,因为用户可能想删除开头的负号,然后重新输入,但这样处理会强制保留开头的负号(如果有的话)。所以,我们可能需要更精确的控制。 我们换一个思路:只允许在开头出现一个负号,其他地方不允许出现负号。那么我们可以: input.value = input.value.replace(/[^0-9-]/g, ''); // 第一步:移除非数字和负号 // 第二步:如果包含负号,则只能有一个,且在开头 if (input.value.includes('-')) { // 将所有的负号删除,然后在开头加一个负号 input.value = '-' + input.value.replace(/-/g, ''); } 但是,这样处理会改变用户输入的顺序,比如用户输入"123-",那么会变成"-123",这可能是期望的。 但是,如果用户输入"12-3",那么会变成"-123",这改变了数值。所以,我们不允许在中间输入负号,所以应该把中间输入的负号删除,只保留开头的负号。 因此,我们这样: function formatInteger(input) { let value = input.value; // 先移除非数字和负号 value = value.replace(/[^0-9-]/g, ''); // 然后,删除所有非开头的负号(即负号不在开头的位置) let hasMinusAtStart = false; if (value.charAt(0)==='-') { hasMinusAtStart = true; // 去掉开头的负号,然后去掉剩余部分的所有负号 value = '-' + value.substring(1).replace(/-/g, ''); } else { // 没有开头的负号,那么去掉所有负号 value = value.replace(/-/g, ''); } input.value = value; } 这个逻辑: - 如果开头有负号,则保留它,然后去掉后面出现的所有负号。 - 如果开头没有负号,则去掉所有负号。 这样,用户在任何位置输入负号,只有开头的负号会被保留,其他位置的负号都会被删除。 但是,如果用户一开始输入了一个负号,然后又在开头输入一个负号(比如在已经有一个负号的情况下,在负号前面再输入一个负号),那么第一个字符是负号,第二个字符也是负号?不会,因为我们在第一个字符是负号后,后面的所有负号都会被删除。所以,在开头连续输入多个负号,会被处理成一个负号。 这个方案比较合理。 但是,我们还需要考虑一种情况:用户可能从中间插入内容,并且插入负号,那么负号会被移到开头吗?不会,我们的逻辑是:如果开头有负号,则保留开头的负号,然后后面部分去掉所有负号;如果开头没有负号,则整个字符串都不允许有负号。所以,在中间插入的负号,如果开头没有负号,那么中间插入的负号会被删除;如果开头有负号,那么中间插入的负号也会被删除。 所以,这个函数满足要求。 但是,这个函数同样会改变光标位置,所以我们需要保存和恢复光标位置。 下面是完整代码(带光标位置修正): function formatInteger(input) { let start = input.selectionStart; let end = input.selectionEnd; let value = input.value; // 处理前 let newValue = value.replace(/[^0-9-]/g, ''); let hasMinusAtStart = false; if (newValue.charAt(0)==='-') { hasMinusAtStart = true; newValue = '-' + newValue.substring(1).replace(/-/g, ''); } else { newValue = newValue.replace(/-/g, ''); } // 如果新值和旧值不同,则更新 if (newValue !== value) { input.value = newValue; // 计算光标位置:因为删除了字符,光标位置需要调整 // 我们这里简单处理:将光标移到新字符串的末尾?或者根据删除的字符数调整? // 更好的做法是计算在旧值中光标之前的字符被删除了多少,然后调整 // 但是这里我们为了简单,将光标移到末尾(因为过滤后字符串通常变短,移到末尾体验不好) // 因此,我们计算新光标位置:光标位置减去被删除的字符数(在光标之前的) let removedBefore = 0; for (let i = 0; i < start; i++) { if (value[i] !== newValue[i-removedBefore]) { removedBefore++; } } let newStart = start - removedBefore; if (newStart < 0) newStart = 0; input.setSelectionRange(newStart, newStart); } } 但是,这个光标位置修正逻辑比较复杂,而且可能不准确。 因此,我们推荐一个更简单的方法:在输入时只允许输入数字和负号,并且负号只能在开头出现一次,其他位置的负号不允许输入(即当用户在其他位置输入负号时,直接忽略)。 我们可以通过keydown事件来阻止非法的负号输入: input.addEventListener('keydown', function(e) { // 如果输入的是负号 if (e.key === '-') { // 如果光标不在开头,或者已经有一个负号了,则阻止输入 if (this.selectionStart !== 0 || this.value.includes('-')) { e.preventDefault(); } } }); 然后,在input事件中,我们只需要过滤掉非数字字符(因为负号已经通过keydown控制,只能出现在开头且只有一个)。 这样,我们只需要: function formatInteger(input) { // 过滤掉非数字字符(负号已经被keydown事件控制,不会出现在非开头位置,且只有一个) input.value = input.value.replace(/[^0-9]/g, ''); // 但是注意,开头的负号我们不想被删除,所以上面的replace会删除负号!所以我们需要调整。 // 因此,我们改为:只删除非数字字符,但保留开头的负号 // 我们可以分两部分:开头的负号(如果有)和后面的数字 let parts = input.value.split(''); let minus = ''; if (parts[0] === '-') { minus = '-'; parts = parts.slice(1); } // 过滤后面的部分,只保留数字 let filtered = parts.map(c => /[0-9]/.test(c) ? c : '').join(''); input.value = minus + filtered; } 但是,这样处理也会改变光标位置。所以,我们结合keydown事件,在keydown中阻止非法负号,在input事件中只过滤非数字字符(除了开头的负号)。但是,这样还是需要处理光标位置。 考虑到复杂度,如果项目要求不高,我们可以使用type="number"并设置step="1",然后通过onchange或onblur事件来修正为整数。 最终,我们给出一个简单实用的方案: <input type="number" step="1" oninput="this.value = parseInt(this.value) || 0"> 但是,这样处理,如果用户输入数字,parseInt会得到NaN,然后被0替代。但是,这样会强制在输入过程中就转换为整数,而且用户可能输入小数,然后立即被取整,体验可能不好。 另外,负整数会被保留,因为parseInt可以处理负号。 但是,如果用户输入一个很大的数,可能会显示科学计数法,所以parseInt可能无法正确转换(但一般不会,因为输入框类型为number,浏览器会处理)。 因此,如果对体验要求不高,可以直接使用: <input type="number" step="1"> 然后,在提交时再转换为整数。 但是,题目要求输入整数,所以我们还是需要确保用户输入的是整数。 考虑到时间和复杂度,我们推荐一个简单方案(不处理光标位置): <input type="text" oninput="this.value=this.value.replace(/[^0-9-]/g,'').replace(/(?!^)-/g,'').replace(/^(-)?-+/,'$1').replace(/(?!^-)-/,'')"> 这个正则比较复杂,我们拆解: 1. replace(/[^0-9-]/g,''):移除非数字和负号 2. replace(/(?!^)-/g,''):移除非开头的负号(负号在开头才保留) 3. replace(/^(-)?-+/,'$1'):如果开头有多个负号,只保留一个(例如,---123变成-123) 4. 但是,第三步后,可能还有非开头的负号(因为第三步只处理开头连续的负号),所以需要第二步。 但是,第二步已经删除非开头的负号,所以第三步是为了处理开头有多个负号的情况(比如--123)。 所以,我们使用: oninput="this.value=this.value.replace(/[^0-9-]/g,'').replace(/(?!^)-/g,'').replace(/^(-)?-+/,'$1')" 这样,用户输入"12-34"会变成"1234",输入"--123"会变成"-123",输入"a-1b2"会变成"-12"。 但是,如果用户输入"-12-3",第二步会删除第二个负号,变成"-123",所以符合要求。 这个方案在大部分情况下是可行的。 综上所述,我们给出两个推荐方案: 方案1(简单,推荐): <input type="text" oninput="this.value=this.value.replace(/[^0-9-]/g,'').replace(/(?!^)-/g,'').replace(/^(-)?-+/,'$1')"> 方案2(使用keydown+input,保留光标位置): <input type="text" id="intInput"> <script> const input = document.getElementById('intInput'); input.addEventListener('keydown', function(e) { if (e.key === '-') { if (this.selectionStart !== 0 || this.value.includes('-')) { e.preventDefault(); } } }); input.addEventListener('input', function() { let value = this.value; let hasMinus = value.charAt(0) === '-'; let newValue = value.replace(/\D/g, ''); this.value = hasMinus ? '-' + newValue : newValue; }); </script> 方案2体验更好,因为光标位置不会跳变,而且过滤简单。 因此,我们推荐方案2。 下面,我们给出方案2的完整代码: <input type="text" onkeydown="integerKeydown(event)" oninput="integerInput(this)"> <script> function integerKeydown(event) { if (event.key === '-') { let input = event.target; if (input.selectionStart !== 0 || input.value.includes('-')) { event.preventDefault(); } } } function integerInput(input) { let value = input.value; let hasMinus = value.charAt(0) === '-'; let newValue = value.replace(/\D/g, ''); input.value = hasMinus ? '-' + newValue : newValue; } </script> 注意:replace(/\D/g, '') 会移除非数字字符,包括负号。但是,我们在keydown中已经阻止了除开头的负号以外的负号输入,而且input事件中,我们保留了开头的负号(如果存在的话),所以这样处理是安全的。 但是,用户可能通过粘贴来输入,所以input事件是必要的。 综上,我们回答完毕。 由于问题只要求输入整数,我们给出了多种方案,并推荐了方案2。 注意:如果输入的是正整数,那么可以不允许负号,就更简单了。 根据题目,我们只要求整数,所以负整数也是允许的。 §§相关问题§§ 1. 如何限制输入框只能输入整数(不包括0和负数)? 2. 在移动端,如何优化数字输入体验(如弹出数字键盘)? 3. 如何实现输入框只能输入小数(保留两位小数)? 4. 在表单提交时,如何验证输入框的内容是否为整数?</think>### 限制 input 输入框只能输入整数的实现方法 以下是几种可靠的技术方案,可根据不同场景选择使用: #### 1. 纯 HTML5 方案(基础限制) ```html <!-- 允许正整数/负整数/零 --> <input type="number" step="1" min="-1000" max="1000" onkeypress="return event.charCode >= 45 && event.charCode <= 57"> ``` **特点**: - `type="number"` 调起数字键盘(移动端友好) - `step="1"` 限制整数输入 - `onkeypress` 限制可输入字符(ASCII 45='-', 48-57=0-9) #### 2. 正则过滤方案(推荐) ```html <input type="text" oninput="this.value=this.value.replace(/[^0-9-]/g,'') // 移除非数字/负号 .replace(/(?!^-)-/g,'') // 删除非开头的负号 .replace(/(\..*?)\..*/g, '$1')" // 防止粘贴小数点 placeholder="输入整数"> ``` #### 3. Vue/React 框架方案 ```vue <template> <input v-model="intValue" @input="validateInt"> </template> <script> export default { data() { return { intValue: '' } }, methods: { validateInt(e) { let val = e.target.value; // 保留开头的负号和数字 this.intValue = val.replace(/[^0-9-]/g, '') .replace(/(?!^-)-/g, ''); } } } </script> ``` #### 4. 进阶方案(带光标位置保护) ```javascript function validateIntegerInput(input) { const start = input.selectionStart; const value = input.value; // 保留开头的负号和数字 let newValue = value.replace(/[^0-9-]/g, '') .replace(/(?!^-)-/g, ''); // 更新值并保持光标位置 input.value = newValue; input.setSelectionRange(start, start); } // 使用示例 document.getElementById('intInput').addEventListener('input', function() { validateIntegerInput(this); }); ``` **关键注意事项**: 1. 负号处理:只允许在开头出现一次 2. 移动端兼容:优先使用 `type="number"` 调起数字键盘 3. 粘贴防护:处理粘贴非整数内容的情况 4. 边界控制:结合 `min`/`max` 属性限制数值范围 5. 表单验证:最终提交时需做服务器端验证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值