一、input输入手机号时的注意事项
需求说明:
用户手机聚焦input后,弹出数字键盘,可以正常输入11位手机号,也可以从电话本复制电话号然后直接执行粘贴操作。
问题说明:
1.input聚焦时弹出数字键盘,type=number时,安卓正常,ios无效。
2.当input type 为number时,input加maxlength限制长度属性无效。
3.ios上粘贴电话号到input中会有空格,且获取不到数据。
问题解决:
- 因为手机号都是数字,为了方便用户体验,我们会选择input聚焦时,手机上直接弹出数字键盘,此时,input type类型应该为:number,设置此属性后,安卓上能够正常显示数字键盘,但是ios不行,此时,需要再加上一个属性:pattern="\d*",pattern用于规定输入内容的模式和格式,加上这两个属性,就可以正常弹出数字键盘,但是ios数字键盘上没有小数点。
示例:
// 使用type=number
// <input type="number“ pattern="\d*" />
// 使用type=tel
<input type="tel" />
2、当type为number时,发现maxlength并不生效,此时可以采用以下方式:
<input type="number" oninput="if(value.length>11)value=value.slice(0,11)" />
// 或者
<input type="number“ pattern="\d*" @input="handleInput" />
...
handleInput(e){
let value = e.target.value + '';
if(value.length > 11){
this.mobile = value.slice(0, 11);
}
}
// 或者
<input type="tel" maxlength="11" />
然后对输入做非数字禁止输入的校验
3、在ios系统上,当input type为number时,将复制的手机号粘贴到input中时,是拿不到数据的,但是在安卓手机上,可以成功复制到手机号;
因为number为数值类型,而复制的手机号是文本类型,可以考虑将number改为text或者tel。
// js
<input type="tel" name="searchText" id="searchText" placeholder="输入用户手机号"
oninput="value=value.replace(/[^0-9]/ig,''); if(value.length>11)value=value.slice(0,11)"
onkeypress="return( /[\d]/.test(String.fromCharCode(event.keyCode) ) )" />
// vue
<input type="tel" pattern="\d*" name="mobile" v-model.trim="mobile" @input="handleInput" placeholder="输入手机号" />
...
handleInput(e){
let value = e.target.value + '';
// 如果有空格,去掉空格
let regSpace = /\s/;
if(regSpace.test(value)){
this.mobile = value.replace(/\s+/g, "");
return;
}
// 限制输入位数
if (value.length > 11) {
this.mobile = value.slice(0, 11);
}
}
4、有的复制手机号,前面会有86,这时候在限制11位的情况下,会截掉后两位,如果有限制位数的需求的话,可以用正则去掉前面的86;
综上几种情况,可以把手机号的输入限制如下:
<input type="tel" v-model.trim="mobile" placeholder="请输入手机号" @input="handleMobile" />
// 1、不能超过11位;2、复制粘贴后,保证只有11位有效电话[去掉86、空格、中间的短横线]
handleMobile(e) {
let value = e.target.value;
// 去掉空格和非数字
value = value.replace(/[^0-9]/ig, '');
// 去掉在电话本中复制的86
let reg1 = /^(\+86)/;
if (reg1.test(value)) {
value= value.slice(3);
}
let reg2 = /^(\86)/;
if (reg2.test(value)) {
value= value.slice(2);
}
// 限制输入位数
if (value.length > 11) {
value = value.slice(0, 11);
}
this.mobile = value;
}
二、输入框禁止输入
1、实现达到条件后禁止表单输入
// js中,必须将当前DOM节点传递出去,修改此节点的value值
<input type="tel" oninput="fn(this)" />
function fn(obj) {
obj.value = obj.value.replace(/[^0-9]/gi,'');
}
// vue,同样修改当前节点的值,不能使用this,可以使用$event,当前事件,用e.target.value获取当前值
@input="fn(e)"
let value = e.target.value
🌰:
// 非数字禁止输入
this.mobile = value.replace(/[^0-9]/ig,'');
// 超过某个数值禁止输入
if(value > 100) {
this.mobile = value.replace(/[^0-9]/ig,'').slice(0, value.length-1);
alert('超过最大数量')
}
2、在vue中使用computed的get和set方式禁止表单输入
当你读取一个变量的时候会触发该变量的getter.
当你修改该变量时候会触发他的setter.
当修改表单中双向绑定的值是,先触发setter,再触发getter
<input type="number" @input="watchCurNum" @blur="defaultCurNum"
v-model.number="curNum" ref="numDom" onpaste = "return false;"/>
data() {
return {
curNum1: 1, // 当前份数
}
}
computed: {
// 份数计算
curNum: {
get() {
let value = this.curNum1;
if (value >= this.maxNum) {
this.$toast({
message: '购买数量超出范围'
})
this.maxFlag = true;
return value;
} else {
this.maxFlag = false;
return value;
}
},
set(val) {
if(val <= this.maxNum) {
this.curNum1 = val;
} else {
this.$forceUpdate();
this.$toast({
message: '购买数量超出范围'
})
}
if(val == 0 && this.curNum1 == '') {
this.curNum1 = ''
}
}
}
}
三、input为number时注意事项
1、input的type为number是,可以输入除了数字之外的:e[e在数学上代表2.71828,也是数字]、+、-、.[小数点]、以及在iOS数字键盘上出现的各种标点符号都可以输入;
但是如果是这样:
<input type="number" v-model="money" placeholder="请输入金额" @input="handleMoney" />
// 依次输入:34e.e.23...e234.e.e
// 控制台打印的value是:3 34 '' '' '' ''
// 即输入非数字的,就获取不到value的值
// 如果输入400.22 控制台可以打印出400.22
// 如果输入400.22.44 控制台可以打印出''
可以考虑用number做输入金额的限制,最多只有一位小数点,但是由于number类型有太多限制,因此使用text
<input type="text" v-model="money" placeholder="请输入金额" @input="handleMoney" />
// 只能输入金额,包含一个小数点,两位小数位;【缺点:不能调起数字键盘】
handleMoney(e) {
let value = e.target.value;
value = value.replace(/[^\d.]/g, '');
value = value.replace('.','$#$').replace(/\./g,'').replace('$#$','.');
value = value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
// 如果第一位是小数点
if(value.indexOf('.') == 0) {
value = '0' + value;
}
this.money = value;
}
2、number基础用法,数值大小限制
min和max只对可操作的上下箭头有效[如下图],还是可以输入任意数值
<input type="number" v-model="number" placeholder="请输入数值" max="10" min="1"/>
四、iOS上使用oninput的问题
问题:我们经常会用oninput监听表单的值变化,做一些正则校验;但是在iOS中,使用oninput并在其中写了类似于"value=value.replace(/\s/g, '')"这样的语句后,会发现输入中文时,会将拼音输入其中,并且maxlength也会失效;
经过查资料,原因是:文本框会填入 “虚拟文本”(待确认文本),同时触发input事件;
因此我们可以修改为在触发compositionend时,就是填入实际内容后(已确认文本),再给输入框赋值:
<input type="text" id="test" v-model="textTest" placeholder="请输入姓名或者身份证" />
var flag = true;
$('#test').on('compositionstart',function(){
flag = false;
})
$('#test').on('compositionend',function(){
flag = true;
})
$('#test').on('input',function(){
var _this = this;
setTimeout(function(){
if(flag){
// console.log(1);
_this.value = _this.value.replace(/\s/g, '').slice(0,6);
}
},0)
})
1、此现象只会出现在oninput方法上,经过验证在Vue中使用@input并不会有此现象
2、限制长度最好使用slice截断,使用maxlength有时候会出现闪烁的现象【尤其是在iOS上输入时,且有待确认文本时】
3、此种限制也可以用在输入框实时搜索中的节流
五、解决IOS12以上微信内置浏览器下键盘收起底部空白的问题
原始做法如下,可以解决问题,但是毕竟粗鲁,在切换输入框时能看到明显的抖动现象;
// 原始做法1:
window.scroll(0,0);
// 原始做法2:
document.body.scrollIntoView();
优化做法,只在iOS中生效,每次切换输入框页面滑动较少【亲测有用】:即在当前页面滚动的位置上下滚动1px的距离即可实现页面的自适应
let _this = this;
let ua = window.navigator.userAgent;
let app = window.navigator.appVersion;
//$alert('浏览器版本: ' + app + '\n' + '用户代理: ' + ua);
if(!!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)){
// alert('ios端');
document.addEventListener('blur', function(e) {
if(['input', 'textarea'].includes(e.target.localName)) {
var currentPosition,timer;
var speed=1;
timer=setInterval(function(){
currentPosition=document.documentElement.scrollTop || document.body.scrollTop;
currentPosition-=speed;
window.scrollTo(0,currentPosition);//页面向上滚动
currentPosition+=speed;
window.scrollTo(0,currentPosition);//页面向下滚动
console.log(currentPosition)
_this.currentPosition = currentPosition;
clearInterval(timer);
},100);
}
}, true)
}else if(ua.indexOf('Android') > -1 || ua.indexOf('Adr') > -1) {
//$alert('android端');
}
六、用addEventListener添加focus事件和blur事件
必须要加true,即
document.getElementById("IdName").addEventListener("focus", myFunctiona,true);
因为input没有::before和::after的微元素