征服number类型的input框

写于2017年11月1日,如有错漏,欢迎斧正。

在移动端H5页面开发中,有时候会有一些数值输入方面的需求。如果需要让用户比较方便地输入小数、负数,最简单的方式是使用number类型的input框,输入时软键盘会切换为数字键盘方便输入(ios是带数字的全键盘,并允许1e5这类的表示方法)。但是在实际使用的时候会面临一个问题,当输入的内容不合法时,比如输入了1...2,此时input会设置自己的状态为invalid,并把value清空。我们可以在css中通过input:invalid来为此input设置输入内容错误的样式,而在js一端,我们却无法知道用户输入的错误内容到底是什么。这个问题是dom本身的特性所置,与我们采用的开发框架无关,不管我们是使用angular、vue还是react,当number类型的input中输入不合法内容时,js就是没有办法知道错误内容是什么,也就没有办法帮助用户修正输入错误。

然而实际需求可不管这个,限制用户输入的数值范围、小数点后精度、是否允许负数等等都是很常见的需求。那怎么办呢?最近看到一篇文章做了一个很无可奈何,但确实很华丽的尝试:一个数字键盘引发的血案——移动端H5输入框、光标、数字键盘全假套件实现。有兴趣可以看一下,这篇文章实现了一个假的键盘来处理这些逻辑。在很复杂的交互和视觉需求下,做一个假键盘也不失为一个终极的解决方案。不过在我看来,处理数字格式、纠错等问题倒可以不用这么麻烦,下面我就分享一下我的思路。

设置一个目标吧:

  1. 允许输入负数
  2. 最多输入5位数
  3. 最多允许两位小数
  4. 自动清除多余的前置0
  5. 自动补充纯小数的整数部分0

虽然定了这么多目标,归根到底只要能得到输入框的输入内容,剩下的就是简单的字符串处理了。那么如何能获取输入内容呢?我的方法是让浏览器选中输入框中所有的内容,然后获取浏览器中选中的字符串,最后清除选中状态。选中输入框中的内容有两种方法:

  1. 最简单的是直接调用input.select()HTMLInputElement.select());
  2. 当输入框已经获得焦点的时候(当然),可以使用document.execCommand('SelectAll')来全选输入框中的所有内容(The selectAll command)。

然而实际上类型的为number的输入框是不允许操作selectRange的,虽然能选中内容,获取输入框中信息,但我在清除选中状态时遇到了问题(也许我代码写得不对),那么采用第二种方法。获取浏览器选中的字符串可以用Window.getSelection().toString()Window.getSelection())。得到实际输入的内容后,我们可以进行一系列的逻辑判断、数值更正。那么最后怎么再把正确的内容写回input框中,同时清除选中状态呢?方法也很多:

  1. 把正确的内容写进clipboard,再粘贴到选中区域,主要使用document.execCommand('copy')document.execCommand('paste')The copy commandThe paste command);
  2. 直接执行一次Undo操作,把输入框内容回退到上一次的正确结果(The undo command);
  3. 执行insertText命令,在选中区域处插入新文本(The insertText command)。

到这里基本上所需要的准备工作都已经完成,试着实践一下:

<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);
    }
});

Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 创建ReactNative工程 最近在学习React-Native开发,是由Facebook出的。把学习经验记录一...
    o_O小薯条阅读 3,777评论 0 0
  • 一年的时间经历了结婚生子,像一场梦,这场梦让我经历了太多的痛苦和无奈。小时候看着电视里无数结婚生子的场景都是美好...
    miss白面阅读 157评论 0 0
  • 《地铁感怀》 嬉闹玩笑快乐 随着列车 驶向远方
    向昕阅读 96评论 0 2