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

Vue.js v2.x无插件实现input输入框手机号掩码适配方法

Vue2 + Vuetify 手机号输入掩码实现方案

核心问题说明

不需要将掩码逻辑放在任何生命周期钩子中承载。你之前直接绑定原生DOM事件、手动修改DOM value的写法不符合Vue的响应式设计逻辑,原有掩码的正则处理逻辑可以直接复用,无需重写。
原有写法存在的问题:

  • 直接在组件标签上写原生onkeypress/onblur属性传入DOM实例,会和v-model双向绑定机制冲突,极易出现输入值、视图显示、绑定变量三者不一致的问题
  • 手动修改DOM节点的value属性绕过了Vue的响应式更新链路,后续做表单校验、值提交时会出现异常

实现步骤

  1. 将原有的mphone掩码处理函数迁移到Vue实例的methods配置中,核心正则逻辑无需修改
  2. 移除标签上的原生事件属性,替换为Vuetify组件支持的@input(输入时触发)、@blur(失焦时触发)事件
  3. 事件触发时直接处理v-model绑定的numero响应式变量,不需要手动操作DOM,也不需要setTimeout等DOM更新延迟逻辑,Vue的响应式系统会自动同步输入框显示内容

完整单文件实现代码

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Phone Mask Demo</title>
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
  <div id="app">
    <v-app>
      <v-container style="max-width: 500px; margin-top: 50px;">
        <v-text-field
          id="phone"
          v-model="numero"
          maxlength="15"
          label="Número com DDD"
          :rules="rulesNum"
          required
          @input="handleMask"
          @blur="handleMask"
        ></v-text-field>
      </v-container>
    </v-app>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
  <script>
    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data() {
        return {
          numero: '',
          rulesNum: [
            v => !!v || 'Campo obrigatório',
            v => v.length >= 14 || 'Número inválido'
          ]
        }
      },
      methods: {
        handleMask() {
          this.numero = this.mphone(this.numero)
        },
        mphone(valueInput) {
          if (!valueInput) return ''
          var regex = valueInput.replace(/\D/g, "");
          regex = regex.replace(/^0/, "");
          if (regex.length > 10) {
            regex = regex.replace(/^(\d\d)(\d{5})(\d{4}).*/, "($1) $2-$3");
          } else if (regex.length > 5) {
            regex = regex.replace(/^(\d\d)(\d{4})(\d{0,4}).*/, "($1) $2-$3");
          } else if (regex.length > 2) {
            regex = regex.replace(/(\d)(\d{4})$/,"$1-$2");
          } else {
            regex = regex.replace(/^(\d*)/, "($1");
          }
          return regex;
        }
      }
    })
  </script>
</body>
</html>

补充说明

  • 上述代码完全保留了你原来的掩码格式规则,输入时实时格式化,失焦时也会自动修正格式,符合(xx)xxxxx-xxxx的巴西手机号格式要求
  • 所有逻辑都在单个HTML文件中,直接打开即可运行,不需要额外构建工具
  • 如果不需要实时输入格式化,只需要失焦时再处理格式,移除@input="handleMask"绑定即可
  • 不要在mounted/created等生命周期里通过document.getElementById获取输入框再绑定事件,Vue框架下通过组件自带的事件绑定即可完成需求,这类手动DOM操作的写法会破坏框架的响应式流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:36:26