写于2017年11月1日,若有错漏,欢迎斧正。javascript
原文css
在移动端H5页面开发中,有时候会有一些数值输入方面的需求。若是须要让用户比较方便地输入小数、负数,最简单的方式是使用number类型的input框,输入时软键盘会切换为数字键盘方便输入(ios是带数字的全键盘,并容许1e5这类的表示方法)。可是在实际使用的时候会面临一个问题,当输入的内容不合法时,好比输入了1...2
,此时input会设置本身的状态为invalid,并把value清空。咱们能够在css中经过input:invalid
来为此input设置输入内容错误的样式,而在js一端,咱们却没法知道用户输入的错误内容究竟是什么。这个问题是dom自己的特性所置,与咱们采用的开发框架无关,无论咱们是使用angular、vue仍是react,当number类型的input中输入不合法内容时,js就是没有办法知道错误内容是什么,也就没有办法帮助用户修正输入错误。html
然而实际需求可无论这个,限制用户输入的数值范围、小数点后精度、是否容许负数等等都是很常见的需求。那怎么办呢?最近看到一篇文章作了一个很迫不得已,但确实很华丽的尝试:一个数字键盘引起的血案——移动端H5输入框、光标、数字键盘全假套件实现。有兴趣能够看一下,这篇文章实现了一个假的键盘来处理这些逻辑。在很复杂的交互和视觉需求下,作一个假键盘也不失为一个终极的解决方案。不过在我看来,处理数字格式、纠错等问题倒能够不用这么麻烦,下面我就分享一下个人思路。vue
设置一个目标吧:java
虽然定了这么多目标,归根到底只要能获得输入框的输入内容,剩下的就是简单的字符串处理了。那么如何能获取输入内容呢?个人方法是让浏览器选中输入框中全部的内容,而后获取浏览器中选中的字符串,最后清除选中状态。选中输入框中的内容有两种方法:react
input.select()
(HTMLInputElement.select());document.execCommand('SelectAll')
来全选输入框中的全部内容(The selectAll command)。然而实际上类型的为number的输入框是不容许操做selectRange的,虽然能选中内容,获取输入框中信息,但我在清除选中状态时遇到了问题(也许我代码写得不对),那么采用第二种方法。获取浏览器选中的字符串能够用Window.getSelection().toString()
(Window.getSelection())。获得实际输入的内容后,咱们能够进行一系列的逻辑判断、数值更正。那么最后怎么再把正确的内容写回input框中,同时清除选中状态呢?方法也不少:ios
document.execCommand('copy')
和document.execCommand('paste')
(The copy command、The paste command);到这里基本上所须要的准备工做都已经完成,试着实践一下:git
<input type="number" id="input"/>
复制代码
const input = document.querySelector('#input');
const format = /-?\d{0,5}(\.\d{0,2})?/;
let lastValue;
input.addEventListener('input', event => {
document.execCommand('SelectAll');
let text = window.getSelection().toString();
if (lastValue !== text) {
const match = text.match(format);
if (!match) {
text = '';
}
else {
text = match[0]
.replace(/^(-?)0+(\d)/, '$1$2') // 删除多余的前置0
.replace(/^(-?)\./, '$10.'); // 插入纯小数的整数0
}
lastValue = text;
document.execCommand('insertText', false, text);
}
});
复制代码
Demogithub