You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js中如何通过v-model实现指定格式的电话号码输入

Vue.js 实现电话号码格式化输入(基于v-model场景)

要实现输入电话号码时自动显示为 (123) - 456 - 78 - 90 的格式,直接用原生v-model无法满足需求,因为它会直接同步原始输入值。我们可以通过拆解双向绑定逻辑,结合输入事件处理和格式化函数来实现,同时保持数据的双向同步。

方案一:组件内直接处理(适合单组件使用)

修改后完整代码

<template>
  <div v-for="(about, index) in abouts" :key="index">
    <!-- 用:value绑定格式化后的显示值,手动处理输入事件 -->
    <input 
      type="text" 
      :value="formatPhone(about.phone)" 
      @input="handlePhoneInput($event, index)"
      placeholder="请输入电话号码"
    >
    <input type="text" v-model="about.mail" placeholder="请输入邮箱">
  </div>
</template>

<script>
export default {
  data() {
    return {
      abouts: [{ phone: '', mail: '' }, { phone: '', mail: '' }]
    }
  },
  methods: {
    // 把纯数字字符串格式化为指定样式
    formatPhone(phone) {
      // 过滤所有非数字字符
      const pureNum = phone.replace(/\D/g, '')
      let formatted = ''
      
      // 按规则拼接格式
      if (pureNum.length > 0) {
        formatted += `(${pureNum.slice(0, 3)}`
        if (pureNum.length >= 3) formatted += ') - '
        if (pureNum.length >= 4) formatted += pureNum.slice(3, 6)
        if (pureNum.length >= 6) formatted += ' - '
        if (pureNum.length >= 7) formatted += pureNum.slice(6, 8)
        if (pureNum.length >= 8) formatted += ' - '
        if (pureNum.length >= 9) formatted += pureNum.slice(8, 10)
      }
      
      // 限制最终显示长度,避免超出格式范围
      return formatted.slice(0, 16)
    },
    // 处理输入事件,同步数据源和显示内容
    handlePhoneInput(event, index) {
      // 提取输入中的纯数字
      const pureNum = event.target.value.replace(/\D/g, '')
      // 更新数据源(存储纯数字,方便后续使用)
      this.abouts[index].phone = pureNum
      // 把格式化后的内容赋值回输入框
      event.target.value = this.formatPhone(pureNum)
    }
  }
}
</script>

逻辑说明

  1. 放弃直接使用v-model,改用:value绑定格式化后的显示内容
  2. handlePhoneInput方法负责:
    • 过滤输入中的非数字字符,只保留有效数字
    • 将纯数字更新到数据源的phone字段
    • 把格式化后的字符串赋值回输入框,实现实时格式化显示
  3. formatPhone方法负责将纯数字字符串按照(XXX) - XXX - XX - XX的规则拼接成目标格式

方案二:自定义指令(适合多处复用)

如果多个组件或页面都需要电话号码格式化,可以封装成自定义指令,提升代码复用性。

完整代码

<template>
  <div v-for="(about, index) in abouts" :key="index">
    <input 
      type="text" 
      v-phone-format="about.phone"
      placeholder="请输入电话号码"
    >
    <input type="text" v-model="about.mail" placeholder="请输入邮箱">
  </div>
</template>

<script>
// 抽离格式化函数
function formatPhone(phone) {
  const pureNum = phone.replace(/\D/g, '')
  let formatted = ''
  
  if (pureNum.length > 0) {
    formatted += `(${pureNum.slice(0, 3)}`
    if (pureNum.length >= 3) formatted += ') - '
    if (pureNum.length >= 4) formatted += pureNum.slice(3, 6)
    if (pureNum.length >= 6) formatted += ' - '
    if (pureNum.length >= 7) formatted += pureNum.slice(6, 8)
    if (pureNum.length >= 8) formatted += ' - '
    if (pureNum.length >= 9) formatted += pureNum.slice(8, 10)
  }
  
  return formatted.slice(0, 16)
}

export default {
  data() {
    return {
      abouts: [{ phone: '', mail: '' }, { phone: '', mail: '' }]
    }
  },
  directives: {
    phoneFormat: {
      // 元素挂载时初始化格式化
      mounted(el, binding) {
        el.value = formatPhone(binding.value)
      },
      // 数据源更新时同步格式化显示
      update(el, binding) {
        if (el.value !== formatPhone(binding.value)) {
          el.value = formatPhone(binding.value)
        }
      },
      // 绑定输入事件处理逻辑
      bind(el, binding, vnode) {
        el.addEventListener('input', () => {
          const pureNum = el.value.replace(/\D/g, '')
          // 更新数据源
          vnode.context[binding.expression] = pureNum
          // 同步格式化显示
          el.value = formatPhone(pureNum)
        })
      }
    }
  }
}
</script>

使用说明

只需要在需要格式化的输入框上添加v-phone-format="数据源字段"即可,指令会自动处理输入格式化和数据同步。

注意事项

  • 数据源中存储的是纯数字字符串,方便后续接口调用、存储等操作,显示层则是格式化后的样式
  • 自动过滤非数字输入,避免用户输入特殊字符导致格式混乱
  • 限制最大输入长度为10位数字,刚好匹配目标格式的位数

内容的提问来源于stack exchange,提问作者oguzcan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:45:13