征服number類型的input框

寫於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

  1. 容許輸入負數
  2. 最多輸入5位數
  3. 最多容許兩位小數
  4. 自動清除多餘的前置0
  5. 自動補充純小數的整數部分0

雖然定了這麼多目標,歸根到底只要能獲得輸入框的輸入內容,剩下的就是簡單的字符串處理了。那麼如何能獲取輸入內容呢?個人方法是讓瀏覽器選中輸入框中全部的內容,而後獲取瀏覽器中選中的字符串,最後清除選中狀態。選中輸入框中的內容有兩種方法:react

  1. 最簡單的是直接調用input.select()HTMLInputElement.select());
  2. 當輸入框已經得到焦點的時候(固然),可使用document.execCommand('SelectAll')來全選輸入框中的全部內容(The selectAll command)。

然而實際上類型的爲number的輸入框是不容許操做selectRange的,雖然能選中內容,獲取輸入框中信息,但我在清除選中狀態時遇到了問題(也許我代碼寫得不對),那麼採用第二種方法。獲取瀏覽器選中的字符串能夠用Window.getSelection().toString()Window.getSelection())。獲得實際輸入的內容後,咱們能夠進行一系列的邏輯判斷、數值更正。那麼最後怎麼再把正確的內容寫回input框中,同時清除選中狀態呢?方法也不少:ios

  1. 把正確的內容寫進clipboard,再粘貼到選中區域,主要使用document.execCommand('copy')document.execCommand('paste')The copy commandThe paste command);
  2. 直接執行一次Undo操做,把輸入框內容回退到上一次的正確結果(The undo command);
  3. 執行insertText命令,在選中區域處插入新文本(The insertText 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

相關文章
相關標籤/搜索