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

如何在Vue中给字符串分别在第3、第2位后插入连字符实现SSN格式掩码

解决方案

你当前代码的问题主要出在三处:1. substr参数使用错误,substr第二个参数是截取长度而非结束下标;2. 退格场景的原始值存储逻辑有问题;3. 替换数字时没有保留连字符。以下是可直接运行的修改后代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue</title>
  </head>
  <body>
    <div id="app">
      <input type="text" @input="onInput" v-model="someData" maxlength="11" />
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
      Vue.filter("ssnMask", function (value) {
        // 先过滤所有非数字字符,避免非法字符干扰
        const pureNum = value.replace(/\D/g, '');
        // 按SSN规则分段:前3位、中间2位、后4位
        let part1 = pureNum.slice(0,3);
        let part2 = pureNum.slice(3,5);
        let part3 = pureNum.slice(5,9);
        let ssnValue = part1;
        // 长度足够时才拼接连字符,避免输入不足时出现多余连字符
        if (part2.length > 0) ssnValue += '-' + part2;
        if (part3.length > 0) ssnValue += '-' + part3;
        // 仅替换数字为*,保留连字符
        return ssnValue.replace(/\d/g, '*');
      });
      const app = new Vue({
        el: "#app",
        data() {
          return {
            someData: "",
            maskedData: "", // 存储用户输入的原始明文,可直接用于后续业务提交
          };
        },
        methods: {
          onInput(e) {
            // 同步存储纯数字明文,兼容退格删除场景
            const inputValue = e.target.value.replace(/\D/g, '');
            this.maskedData = inputValue;
            // 生成掩码赋值给输入框绑定值
            this.someData = this.$options.filters.ssnMask(e.target.value);
          },
        },
      });
    </script>
  </body>
</html>

效果说明

  • 输入1-3位时,直接显示对应数量的*,无连字符
  • 输入4-5位时,格式为***-*到***-**
  • 输入6位及以上时,格式为***-**-*到***-**-****,最多支持9位输入
  • 退格删除逻辑正常,不会出现无法删除的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:36:02