Skip to content

输入框输入手机号分隔为 344 格式

目前有两种实现方式。一种是利用 Vue 的计算属性的 get 和 set 钩子。一种是利用命令式编程。

手机号 3-3-4 分割正则

js
// 适合纯 11 位手机
const splitMobile = (mobile, format = '-') => {
  return String(mobile).replace(/(?=(\d{4})+$)/g, format)
}
// 适合 11 位以内的分割
const splitMobile2 = (mobile, format = '-') => {
  return String(mobile).replace(/(?<=(\d{3}))/, format).replace(/(?<=([\d\-]{8}))/, format)
}

console.log(splitMobile(18379802267)) // 183-7980-2267
console.log(splitMobile2(18379876545)) // 183-7987-6545

计算属性的 get 和 set

可以删除空格

手机号19122544462修改

命令式编程

不可以删除空格

手机号19122544462修改

index.vue 文件:

vue
<template>
  <div 
    class="border-rounded border 
  border-gray border-solid p-20px text-gray flex
    items-center w-full box-border"
  >
    <span>手机号</span>
    <span class="ml-auto">{{ tel }}</span>
    <span class="w-0.5px self-stretch h-20px mx-10px bg-gray"></span>
    <span class="color-#4a7bff cursor-grab" @click="modify">修改</span>
  </div>
  <modifyTelModalVue1 ref="modifyTelModal1" @confirmModifyProductNo="confirmModifyProductNo"/>
  <modifyTelModalVue2 ref="modifyTelModal2" @confirmModifyProductNo="confirmModifyProductNo"/>
</template>
<script setup>
import { ref } from 'vue'
import modifyTelModalVue1 from './components/modifyTelModal1.vue'
import modifyTelModalVue2 from './components/modifyTelModal2.vue'

const props = defineProps({
  num: {
    type: Number,
    required: true
  }
})

const tel = ref('19122544462')

const modifyTelModal1 = ref(null)
const modifyTelModal2 = ref(null)

function modify() {
  props.num === 1 ?
    modifyTelModal1.value.show(tel.value)
    :
    modifyTelModal2.value.show(tel.value)
}

function confirmModifyProductNo(value) {
  tel.value = value
}
</script>

弹框一代码

vue
<template>
  <div v-if="isShowModifyModal" class="fixed left-0 top-0 w-full h-full bg-black/50 z-999">
    <div
      class="fixed bg-white left-50% top-50% -translate-x-1\/2
      -translate-y-1\/2 z-9999 border-rounded"
    >
      <div class="w-281px pt-24px">
        <div class="text-center font-600 text-17px color-#242424 mb-15px">
          修改手机号
        </div>
        <div class="flex flex-col px-24px">
          <input 
            v-model="bizPhoneNo" 
            class="text-15px box-border p-10px w-full outline-unset border-none rounded-8px
            bg-#f2f2f2 placeholder-#aaa"
            ref="modifyPNInput" 
            maxlength="13" 
            placeholder="请输入你要修改的手机号" 
            type="tel" 
          />
          <div class="box-border p-10px w-full text-13px flex items-center h-25px text-#ee0a24">
            <div v-if="errorMessage">手机号输入有误</div>
          </div>
        </div>
        <div class="text-17px text-#242424 flex items-center justify-center text-center h-45px">
          <div 
            class="relative flex items-center justify-center flex-auto text-#333 rounded-8px h-45px
            after:absolute after:left-0 after:top-0 after:w-100% after:h-1px after:bg-#e9e9e9 after:scale-y-50" 
            @click="confirm(false)"
          >
            取消
          </div>
          <div class="h-full w-1px bg-#e9e9e9 scale-x-50 flex-none"></div>
          <div 
            class="relative flex items-center justify-center flex-auto text-#333 rounded-8px h-45px
            after:absolute after:left-0 after:top-0 after:w-100% after:h-1px after:bg-#e9e9e9 after:scale-y-50" 
            @click="confirm(true)"
          >
            确认
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
	props: {},
	data() {
		return {
			isShowModifyModal: false, // 是否显示修改手机号弹框
			inModalProductNo: '', // 在修改手机号弹框里显示的号码
			errorMessage: false
		};
	},
	computed: {
		bizPhoneNo: {
			set(val) {
				const value = val.replace(/\s/g, '');
				this.inModalProductNo = value;
				if (/^1[3456789]\d{9}$/.test(value)) {
					this.errorMessage = false;
				} else {
					this.errorMessage = true;
				}
			},
			get() {
				return this.formatPhone(this.inModalProductNo);
			}
		}
	},
	methods: {
		show(value) {
			this.isShowModifyModal = true;
			this.inModalProductNo = value;
			this.$nextTick(() => {
				this.$refs.modifyPNInput.focus();
			});
		},
    /*
    * 对手机号中添加空格
    */
    formatPhone(str) {
      const phone = str || '';
      return phone
        .replace(/\s/g, '')
        .replace(/(^\d{3})(?=\d)/g, '$1 ')
        .replace(/(\d{4})(?=\d)/g, '$1 ')
        .replace(/(\d{4})(?=\d)/g, '$1 ');
    },
		confirm(flag) {
			if (flag) {
				let regex = /^1[3456789]\d{9}$/;
				if (regex.test(this.inModalProductNo)) {
					// 符合要求,修改手机号
					this.$emit('confirmModifyProductNo', this.inModalProductNo);
					this.isShowModifyModal = false;
				} else {
					// 不符合要求
					this.errorMessage = true;
				}
			} else {
				this.errorMessage = false;
				this.isShowModifyModal = false;
			}
		}
	}
};
</script>

<style lang="scss" scoped>

</style>

弹框二代码

vue
<template>
  <div v-if="isShowModifyModal" class="fixed left-0 top-0 w-full h-full bg-black/50 z-999">
    <div
      class="fixed bg-white left-50% top-50% -translate-x-1\/2
      -translate-y-1\/2 z-9999 border-rounded"
    >
      <div class="w-281px pt-24px">
        <div class="text-center font-600 text-17px color-#242424 mb-15px">修改手机号</div>
        <div class="flex flex-col px-24px">
          <input
            ref="modifyPNInput"
            placeholder="请输入你要修改的手机号"
            type="tel"
            maxlength="13"
            @input="onInput"
          />
          <div class="box-border p-10px w-full text-13px flex items-center h-25px text-#ee0a24">{{ errorMessage }}</div>
        </div>
        <div class="text-17px text-#242424 flex items-center justify-center text-center h-45px">
          <div class="relative flex items-center justify-center flex-auto text-#333 rounded-8px h-45px
            after:absolute after:left-0 after:top-0 after:w-100% after:h-1px after:bg-#e9e9e9 after:scale-y-50" 
            @click="confirm(false)"
          >
            取消
          </div>
          <div class="h-full w-1px bg-#e9e9e9 scale-x-50 flex-none"></div>
          <div 
            class="relative flex items-center justify-center flex-auto text-#333 rounded-8px h-45px
            after:absolute after:left-0 after:top-0 after:w-100% after:h-1px after:bg-#e9e9e9 after:scale-y-50" 
            @click="confirm(true)"
          >
            确认
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
	props: {},
	data() {
		return {
			isShowModifyModal: false, // 是否显示修改手机号弹框
			inModalProductNo: '', // 在修改手机号弹框里显示的号码
			errorMessage: ''
		};
	},
	methods: {
		show (value) {
			this.isShowModifyModal = true
			this.$nextTick(() => {
				this.setValue(value)
				this.$refs.modifyPNInput.focus()
			})
		},
		onInput(e) {
      const inputValue = e.target.value
      // 只保留数字
      let onlyNumber = this.getOnlyNumber(inputValue)
			this.setValue(onlyNumber)
    },
		setValue(operateValue) {
      const length = operateValue.length
      if(length <= 3) {
				//
      } else if (3 < length && length <= 7) {
        operateValue = `${operateValue.substring(0, 3)} ${operateValue.substring(3)}`
      } else if (7 < length) {
        operateValue = `${operateValue.substring(0, 3)} ${operateValue.substring(3, 7)} ${operateValue.substring(7)}`
      }
      this.$refs.modifyPNInput.value = operateValue
			this.isOK()
		},
		getOnlyNumber(value) {
			return value.replace(/\D/g, "");
		},
		getRealTel() {
			return this.getOnlyNumber(this.$refs.modifyPNInput.value)
		},
		confirm(flag) {
			if (flag) {
				if (this.isOK()) {
					// 符合要求,修改手机号
					this.$emit('confirmModifyProductNo', this.getRealTel())
					this.isShowModifyModal = false
				} else {
					// 不符合要求
				}
			} else {
				this.isShowModifyModal = false
			}
		},
		isOK() {
			let regex = /^1[3456789]\d{9}$/;
			const realTel = this.getRealTel()
			if (regex.test(realTel)) {
				this.errorMessage = ''
				return true
			} else {
				this.errorMessage = '手机号格式错误'
				return false
			}
		}
	}
};
</script>

Released under the MIT License.