input|input 输入控制-原生和vue的指令方式
我们经常会要求用户在文本框中输入特定的数据,或者输入特定格式的数据.例如,必须包含木屑字符,或者必须匹配某种模式.由于文本框在默认情况下没有提供多少验证数据的手段,因此必须是哟个JavaScript来完成此类过滤输入的操作.而综合运用事件和DOM手段,就可以将普通的文本框转换成能够理解用户输入数据的工程型控件.
1.原生事件方法:
- input事件操作el.value值
此处按照事件的顺序均可实现
【input|input 输入控制-原生和vue的指令方式】
onkeydown
,onkeypress
都有一个比较明显的缺点,就是非数组字符仍可以输入,只是在下一次输入之后才会替换掉.keyup
事件能在输入不正确的字符之后立刻就能清除掉, 但是这个动作还是人眼可见的.封装 : 此种方式也可先定义一个函数,将
this
传递到该函数然后进行复杂操作
- 最佳方案
event.preventDefault
为了让不希望输入的字符不会在input框中闪现,可以通过阻止某个按键的默认行为来屏蔽此类字符.在极端的情况下,可以通过下列代码屏蔽所有按键操作.
EventUtil.addHandler(textBox,"keypress",function(event){
event=EventUtil.getEvent(event);
EventUtil.preventDefault(event);
})
放上用到的
EventUtil
公共方法let EventUtil = {
addHandler: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, hander);
} else {
element["on" + type] = handler;
}
},
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
getEvent: function (event) {
return event ? event : window.event;
},
getTarget: function (event) {
return event.target || event.srcElement;
},
preventDefault: function (event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = https://www.it610.com/article/false;
}
},
stopPropagation: function (event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getCharCode: function (event) {
if (typeof event.charCode ==="number") {
return event.charCode;
} else {
return event.keyCode;
}
},
getClipboardText: function (event) {
var clipboardData = https://www.it610.com/article/(event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
setClipboardText: function (event, value) {
if (event.clipboardData) {
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData) {
return window.clipboardData.setData("text", value);
}
}
}
运行以上代码后,由于所有按键操作都被屏蔽,结果会导致文本框变成只读的.如果只想屏蔽特定的字符,则需要检测keypress事件对应的字符编码,然后再决定如何响应.例如,下列代码只允许用户输入数值.
例子中,使用EventUtil.getCharCode()实现了跨浏览器取得字符编码,然后使用String.fromCharCode()将字符编码转换成字符串,再使用正则表达式/\d/来测试该字符串,将测试失败的数值使用EventUtil.preventDefault()屏蔽按键事件.
- vue指令方式
通过vue指令可以在input 标签上添加相应指令名称就可以达到操作原生input事件,满足各种input功能需求, 逻辑即清晰亦是解耦,可移植性强.
- 限制input输入数字最大最小值
下面是我封装后的完整示例:
HTML部分
input 控制输入
JavaScript部分
// 截取精确小数方法
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
Vue.directive('int-num', {
bind: function (el, binding, vnode) {
let {
cb,//回调函数,可在不满足条件的情况下做一下后续提示等操作
min,//最小值
max,//最大值
decimal //精确小数位数
} = binding.value ? binding.value : {
cb: Function,
min: 0,
max: 100,
decimal: 0
};
if (min > max) {
throw new Error("最小值不能大于最大值");
return;
}el.keypressHandler = function (event) {
// 当小数位数位0时,此时不允许输入'.'点符号
if (decimal === 0 && event.charCode === 46) {
event.preventDefault();
//组织默认行为
event.stopPropagation();
//停止传递冒泡事件,不会进入input事件中
}
}
el.inputHandler = function (event) {
if (isNaN(Number(el.value))) {
el.valuehttps://www.it610.com/article/= "";
} else {
el.value = https://www.it610.com/article/round(Number(el.value), decimal);
}
cb.call(null, Number(el.value));
if (el.value> max) {
el.value = https://www.it610.com/article/max;
}
}
el.blurHandler = function () {
if (el.value> max) {
cb.call(this, "最大值是 " + max)
}
if (el.value < min) {
cb.call(this, "最小值是 " + min);
}
}
// 添加事件监听
el.addEventListener("keypress", el.keypressHandler)
el.addEventListener('input', el.inputHandler);
el.addEventListener("blur", el.blurHandler);
},
unbind: function (el) {
// 移除事件监听
el.removeEventListener("keypress", el.keypressHandler)
el.removeEventListener('input', el.inputHandler);
el.removeEventListener("blur", el.blurHandler);
}
});
new Vue({
el: "#app",
data: {
value: ""
},
methods: {
showAlert(e) {
console.info(JSON.stringify(e));
}
}
})
特别注意:其实内部实现也是input事件的原生方法,经过vue指令的封装,控制输入行为会更灵活,也更直观和方便.
v-model
值绑定的时候需要使用.lazy
进行修饰,因为v-model
内部也是用input
事件截取值和绑定值的,哪个先执行是不确定的,偶尔会看到input值闪动出现。当用.lazy
修饰之后,v-model
内部使用change
事件绑定值,而change事件是在input事件之后,故此时已经是经过自定义处理之后的值,不会出现数值跳动的情况。
如果需要对特定字符进行组织或只允许输入特定字符,可以在keypress事件中用
event.charCode
判断即可实现.题外话:
为了只允许输入数字可以用input[type=number]和input[type=tel],但是有一些缺陷
- input[type=number]
不支持maxlength,支持输入e
,.
- input[type=tel]
在移动设备上,input[type=tel] 是支持maxlength的,而且只能输入数字键盘。支持输入#
,*
,+
推荐阅读
- Node.js中readline模块实现终端输入
- 我的拖延症如何控制了我,又一次
- 真正的爱
- 大语文4
- 每天听本书《控制焦虑》
- 控制自己的心为什么这么难([追光日记(第2篇)])
- 《不要用爱控制我》
- 8、Flask构建弹幕微电影网站-搭建后台页面-密码修改、主页控制面板
- Promise|Promise 异步控制流
- 孕期血糖有点高怎么办(如何控制孕期血糖?看完觉得隐隐作痛)