【问题标题】:Add delimiter to string at irregular lengths - Javascript以不规则长度向字符串添加分隔符 - Javascript
【发布时间】:2021-02-04 07:54:04
【问题描述】:

我正在研究自动填充的连字符是 HTML 输入字段的不规则长度。

After the 2nd digit/character
After the 6th digit/character
After the 13th digit/character
12-3456-7891234-00000

我想出了下面的代码,它可以很好地添加连字符。然而,使用退格键会破坏逻辑。无论如何我可以使用正则表达式来实现这一点,也许它会考虑整个字符串来处理拆分?

var newFoo = '';
$('.nzPhoneNumber').on('change keydown paste input', function(){
  var foo = $(this).val();
  if (foo.length === 2) {
    newFoo = foo.concat('-')
    $(this).val(newFoo);
  } else if (foo.length === 7) {
    newFoo = newFoo + foo.substring(3,7) + '-'
    $(this).val(newFoo);
  } else if (foo.length === 15) {
    newFoo = newFoo + foo.substring(8,15) + '-'
    $(this).val(newFoo);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="nzPhoneNumber" />

Repl Link

【问题讨论】:

  • 使用单独的“输入值”与“显示值”。或者检查插入符号的位置(并在.val(newval) 之后恢复它)以查看它是在破折号之后(在退格上)还是在破折号之前(在删除时)。您还可以在用户诅咒时移动插入符号(但不会在退格/删除问题之前/之后修复)
  • 此外,还有大量的“屏蔽输入框”jquery 插件。不要重新发明轮子!
  • 嘿,伙计@WiktorStribiżew,这很好用。我花了将近 2 个小时才明白你在那里做了什么!对我来说很好的学习曲线。如果您可以将其作为答案发布,我很乐意接受此答案。
  • @SubSul 添加了 fixed version 并附有解释和另一种选择。

标签: javascript jquery regex string


【解决方案1】:

您可以使用将匹配连续可选模式并替换为自定义逻辑的模式。

代码如下:

const re  = /^(\d{2})(?:(\d{1,4})(?:(\d{1,7})(\d*))?)?$/;

$('.nzPhoneNumber').on('change keydown paste input', function(){
  var foo = $(this).val();
  $(this).val(foo.replace(/\D/g,'').replace(re, (_,a,b,c,d) =>  
   a + 
    ( b ? `-${b}` : "") + 
     ( c ? `-${c}` : "") + 
      ( d ? `-${d}` : "") ));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="nzPhoneNumber" />

详情

  • .replace(/\D/g,'') - 第一个动作是从输入字符串中删除所有非数字字符
  • .replace(re, (_,a,b,c,d) =&gt; - 现在替换为自定义正则表达式,一旦找到匹配项,将第 1 组分配给 a,第 2 组分配给 b,第 3 组分配给 c,第 4 组分配给d
  • a + ( b ? `-${b}` : "") + ( c ? `-${c}` : "") + ( d ? `-${d}` : "") ) - 这是动态构建的替换字符串:首先,a 在开头使用(因为它总是匹配),然后 - + 如果第 2 组完全匹配,则添加第 2 组值,否则为空字符串附加到a,接下来,- + 如果第 3 组匹配,则添加第 3 组值(否则附加一个空字符串),然后在第 4 组 (d) 上发生同样的事情。

/^(\d{2})(?:(\d{1,4})(?:(\d{1,7})(\d*))?)?$/ 模式匹配:

  • ^ - 字符串开头
  • (\d{2}) - 捕获组 1:两位数
  • (?:(\d{1,4})(?:(\d{1,7})(\d*))?)? - 一个可选序列(注意每个后续模式只有在前一个匹配时才能匹配):
    • (\d{1,4}) - 第 2 组:一到四位数
    • (?:(\d{1,7})(\d*))?)? - 可选序列
      • (\d{1,7}) - 第 3 组:一到七位数
      • (\d*) - 零到五位数
  • $ - 字符串结束。

请参阅regex demo

注意:如果最后一个数字不能超过五位,请使用(?:(\d{1,5})\d*)? 而不是最后一个(\d*)/^(\d{2})(?:(\d{1,4})(?:(\d{1,7})(?:(\d{1,5})\d*)?)?)?$/

【讨论】:

    【解决方案2】:

    一般创建输入格式在退格和选择字符串长度时会出现问题。您应该在事件中排除退格键或在字符串的目标长度上添加一个数字(这是因为防止在退格删除字符串时产生问题)。

    无论如何我选择了第二种情况。所以我在你的目标长度上加了一个。还使用了数组、循环和正则表达式来简化代码。

    $('.nzPhoneNumber').on('change keydown paste input', function(e){
      var foo = $(this).val();
      [3, 8, 16].forEach((item) => {
        if (foo.length == item)
          $(this).val(foo.replace(/(\d)(?=\d$)/, "$1-"));
      })
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input type="text" class="nzPhoneNumber" />

    【讨论】:

    • 这个解决方案不好。输入 N 个整数,将脱字符号移到字符串的开头,然后开始插入新整数。
    • @Mohammad 感谢您的回答,正如前面的评论所提到的,在编辑中间的字符时逻辑会起作用,我尝试修复它但无法弄清楚。无论如何,谢谢,cmets中提到的答案很好。
    猜你喜欢
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    • 2021-02-07
    • 2015-01-06
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    相关资源
    最近更新 更多