Skip to content

Input 输入框仅支持 11 位手机号输入

Published: at 09:04 AMSuggest Changes

上一周公司的一个项目中发现了一个问题:有一个输入框是要输入手机号码的,但是这个输入框当时没有做限制,可以输入任意字符,所以被报了 BUG。

需求:这个输入框只能输入 11 位手机号

我一看,这不是很简单的事情吗,但是实现的时候,发现事情并没有那么简单。

解决方法

常见的解决方法

<input
  type="text"
  onkeyup="this.value=this.value.replace(/[^0-9]/gi, '').slice(0,11)"
/>

一行解决,但效果不太好,如图。

试一下 onkeypress

<input
  type="text"
  oninput="this.value = this.value.replace(/[^0-9]/gi, '').slice(0,11);"
/>

这代码有问题,还能输入其他字符?

改了一下代码

<input type="text" onkeypress="validate(event)" />
function validate(evt) {
  var theEvent = evt || window.event;

  // Handle paste
  if (theEvent.type === "paste") {
    key = event.clipboardData.getData("text/plain");
  } else {
    // Handle key press
    var key = theEvent.keyCode || theEvent.which;
    key = String.fromCharCode(key);
  }
  var regex = /[0-9]|\./;
  if (!regex.test(key)) {
    theEvent.returnValue = false;
    if (theEvent.preventDefault) theEvent.preventDefault();
  }
}

这次效果是不是好很多了?然而,如果用户右键复制粘贴,强行输入了字符串怎么办?

继续改,换个监听方式,oninput

<input
  type="text"
  oninput="this.value = this.value.replace(/[^0-9.]/gi, '').replace(/\./g, '').slice(0,11);"
/>

这次效果是不是好很多了?

还有网上找来的一些成熟的方法

function setInputFilter(textbox, inputFilter) {
  [
    "input",
    "keydown",
    "keyup",
    "mousedown",
    "mouseup",
    "select",
    "contextmenu",
    "drop",
  ].forEach(function (event) {
    textbox.addEventListener(event, function () {
      if (inputFilter(this.value)) {
        this.oldValue = this.value;
        this.oldSelectionStart = this.selectionStart;
        this.oldSelectionEnd = this.selectionEnd;
      } else if (this.hasOwnProperty("oldValue")) {
        this.value = this.oldValue;
        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
      } else {
        this.value = "";
      }
    });
  });
}

setInputFilter(document.getElementById("myTextBox"), function (value) {
  return /^\d*\.?\d*$/.test(value);
});

然而,事情还没那么简单

我浏览器 F12 看了一下代码,发现,代码是 jsp 生成的,jsp 调用了某个 js 文件,这个 js 文件有点像生成模板字符串那样,生成了这个输入框。然后这个 js 文件我也不敢乱改,因为它是个公共组件,我改了的话,其他地方不知道又要出什么 BUG。F12 看到的 DOM 类似下面这种。

<input type="text" name="txt" value="Hello" onchange="myFunction(xxxx, this)" />

其中 myFunction 函数我还是可以改的。

我就改成下面这种了

function (data, el) {
// 对于手机字段,限制只能输入数字,个数不超过 11 位
  if (type == "phone") {
  	var val = $(el).val();
  	val = val.replace(/[^0-9]/gi, "").slice(0,11);
  	$(el).val(val);
  	$(el).off("oninput");
  	$(el).on("oninput", function (event) {
      val = val.replace(/[^0-9]/gi, '').slice(0,11);
  	});
  }
}

onchange 会触发 myFunction,这时候加上 oninput 的事件监听就可以了。

由于每次 onchange 都会触发一遍 myFunction,所以要去掉 oninput 的事件监听,不然的话输入一次会加一次监听,输入 11 次,就会挂上 11 次的事件监听,就会执行 11 次事件。 虽然用户无感知,但是养成好习惯是有必要的。

其他笔记

事件监听的添加和移除

// Attach an event handler to <div>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);

// Remove the event handler from <div>
document.getElementById("myDIV").removeEventListener("mousemove", myFunction);

onchange 没有 preventDefault()

onchange 事件的 event 是没有的 preventDefault() 的,见 cancelable

相关资料

参考文章

总结

一个小小的输入框校验,让我收获了很多。


Previous Post
使用 Local Overrides 调试压缩的 JavaScript 文件
Next Post
Webpack 取消对 require 处理的几种方式