這一個小需求,斷斷續續解決了很久,中間一直存在各類bug,如今基本上已經徹底解決,所以,打算從頭至尾記錄一下,方便之後查詢。javascript
開始的時候,仍是把需求簡單的說下:css
移動端中,彈出系統的數字鍵盤,實現344分割手機號
需求明確以後,下面就是分析需求,而後才能肯定實現方式:html
type="phone"
的input輸入框watch
來實現通過分析能夠看出,實際須要使用的知識點並非不少。分析完成以後,下面就要來具體實現這個需求了。vue
首先,在寫真正的程序以前,要把結構搭建完成,後續寫代碼直接在結構中寫就能夠了。html5
type
和maxlength
v-model
實現數據的雙向綁定<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style type="text/css"> /* 自定義input輸入框的樣式 */ #app input { width: 100%; height: 50px; border: 1px solid red; font-size: 30px; outline: none; } </style> </head> <body> <div id="app"> <!-- 設置type和maxlength,並實現數據雙向綁定 --> <input v-model="phone" type="phone" placeholder="請輸入手機號" maxlength="13"> </div> </body> </html> <script type="text/javascript" src="./vue2.4.2.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data() { return { phone: '' } }, watch: { phone(newValue, oldValue) { // 具體的代碼在這裏實現 } } }) </script>
在具體實現以前,首先要明白,輸入和輸出的分別觸發什麼樣的操做。
下面,咱們把watch中的newValue
和oldValue
的值輸出,看一下規律。java
phone(newValue, oldValue) { // 具體的代碼在這裏實現 console.group('< === 是不是輸入 === >') console.log("%c%s", "color:red", `${newValue.length > oldValue.length}`) console.groupEnd('< === 是不是輸入 === >') }
當在輸入框中輸入內容的時候:正則表達式
當在輸入框中刪除內容的時候:app
從分析能夠看出,在輸入的時候,長度是增長的,刪除的時候,長度是減小的。工具
在刪除的時候,會出現兩個轉折點,就是在刪除第10個元素或者第5個元素的時候,要自動刪除空格。優化
很明顯,這裏出現了兩個條件,下標爲4的時候和下標爲9的時候,要去除字符串的空格。
phone(newValue, oldValue) { // 具體的代碼在這裏實現 if (newValue.length > oldValue.length) { // ... } else { if (newValue.length === 9 || newValue.length === 4) { this.phone = this.phone.trim() } } }
代碼寫出了以後,看着有些不舒服,有沒有優化方案呢?
再次通過分析會發現,既然在下標爲4或9的時候,咱們作的事是去除空格,那麼就能夠根據去空格的特性(有空格去除空格,無空格不進行處理),直接只作去除空格的操做,不進行判斷了。
phone(newValue, oldValue) { // 具體的代碼在這裏實現 if (newValue.length > oldValue.length) { // ... } else { this.phone = this.phone.trim() } }
如今,刪除的功能實現了,而且代碼也進行了優化,下面開始實現輸入的操做。
下面來分析一下輸入的問題:
在輸入的時候,當值的長度小於3的時候,確定是原樣返回的;當值的長度大於等於3且小於7的時候,要增長一個空格;當長度大於等於7的時候,要增長兩個空格。這個時候就要牽涉到條件判斷了。
另外,在判斷值的時候,確定是判斷總數字的個數,所以是去除空格的。
phone(newValue, oldValue) { // 具體的代碼在這裏實現 if (newValue.length > oldValue.length) { if (newValue.replace(/\s/g, '').length < 3) { this.phone = newValue.replace(/\s/g, '') } else if (newValue.replace(/\s/g, '').length >= 3 && newValue.replace(/\s/g, '').length < 7) { this.phone = newValue.replace(/\s/g, '').replace(/(\d{3})/, '$1 ') } else if (newValue.replace(/\s/g, '').length >= 7) { this.phone = newValue.replace(/\s/g, '').replace(/(\d{3})(\d{4})/, '$1 $2 ') } } else { this.phone = this.phone.trim() } }
個人天哪,這個代碼怎麼看着那麼亂,應該能夠優化的。因爲正則表達式是一個強大的工具,所以,能夠結合正則來優化。
首先,咱們能夠把空格做爲分割點,那麼空格以前的內容屬於一組,因此共分三組。第一組的長度爲3個數字,第二組和第三組的長度都是0-4個數字,所以,經過正則能夠簡化代碼:
phone(newValue, oldValue) { // 具體的代碼在這裏實現 if (newValue.length > oldValue.length) { this.phone = newValue.replace(/\s/g, '').replace(/(\d{3})(\d{0,4})(\d{0,4})/, '$1 $2 $3') } else { this.phone = this.phone.trim() } }
上面的代碼已經基本算精簡了,但是,若是使用三目運算符,還能夠更加精簡:
phone(newValue, oldValue) { // 具體的代碼在這裏實現 this.phone = newValue.length > oldValue.length ? newValue.replace(/\s/g, '').replace(/(\d{3})(\d{0,4})(\d{0,4})/, '$1 $2 $3') : this.phone.trim() }
至此,該需求已經完成了,最後實際的代碼只有一句。
其實這個需求很簡單,須要總結的東西很少,所以,在這裏把具體的代碼實現貼出來,方便後續使用:
<div id="app"> <!-- 設置type和maxlength,並實現數據雙向綁定 --> <input v-model="phone" type="phone" placeholder="請輸入手機號" maxlength="13"> </div> <script type="text/javascript" src="./vue2.4.2.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data() { return { phone: '' // 雙向綁定的數據 } }, watch: { phone(newValue, oldValue) { // 監聽 this.phone = newValue.length > oldValue.length ? newValue.replace(/\s/g, '').replace(/(\d{3})(\d{0,4})(\d{0,4})/, '$1 $2 $3') : this.phone.trim() } } }) </script>