这一个小需求,断断续续解决了很久,中间一直存在各类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>