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

如何实现带固定段与占位符的输入掩码,支持填充与回退恢复

输入掩码实现问题

预设条件

已声明常量:

const begin = '1234';
const end = '789';

HTML输入框预设值为 1234-56??-????-0987,需要实现输入掩码满足以下需求:

  • 用户输入数字(如7)时,输入值变为 1234-567?-????-0987
  • 继续输入8后,值变为 1234-5678-????-0987
  • 当所有?被替换后,停止接受输入
  • 用户按退格/删除数字时,对应的?重新显示

当前代码及问题

目前使用的代码:

const start = '123456';
const end = '0987';
const input = document.getElementById('entry-number');
input.addEventListener('input', () => 
{
    const mask = "******";
    const userInput = input.value.replace(/\D/g, "").replace(start, "").replace(end, "");
    const newNumber = start + userInput + mask.slice(userInput.length) + end;
    input.value = newNumber;
});

存在两个问题:

  1. 不支持带连字符的掩码格式
  2. 按退格键会导致输入值异常

方案一:原生JavaScript实现

核心思路是保留掩码的格式结构,跟踪用户输入的数字,精准替换对应位置的?,同时处理退格/删除的回退逻辑,控制输入长度:

const input = document.getElementById('entry-number');
// 原始掩码模板,用于重置对应位置
const maskTemplate = '1234-56??-????-0987';
// 拆分模板字符,提取所有可填充的?的位置索引
const fixedChars = maskTemplate.split('');
const fillableIndices = fixedChars.map((char, idx) => char === '?' ? idx : null).filter(idx => idx !== null);
const maxInputLength = fillableIndices.length;

let userInputs = []; // 存储用户输入的数字

input.addEventListener('input', (e) => {
    const inputValue = e.target.value;
    // 提取所有数字字符
    const rawDigits = inputValue.replace(/[^0-9]/g, '');
    // 提取模板中的固定数字部分:1234560987
    const fixedDigits = maskTemplate.replace(/[^0-9]/g, '');
    // 过滤出用户输入的有效数字(剔除固定部分)
    let newUserDigits = rawDigits.replace(new RegExp(`^${fixedDigits.slice(0, 6)}|${fixedDigits.slice(6)}$`, 'g'), '');
    // 限制输入长度不超过可填充位置数
    newUserDigits = newUserDigits.slice(0, maxInputLength);
    
    // 更新用户输入数组
    userInputs = newUserDigits.split('');
    
    // 重新构建带格式的掩码值
    const newValue = [...fixedChars];
    userInputs.forEach((digit, idx) => {
        if (fillableIndices[idx]) {
            newValue[fillableIndices[idx]] = digit;
        }
    });
    
    // 未填充的位置恢复为?
    for (let i = userInputs.length; i < maxInputLength; i++) {
        newValue[fillableIndices[i]] = '?';
    }
    
    e.target.value = newValue.join('');
});

// 优化退格/删除后的光标位置
input.addEventListener('keydown', (e) => {
    if (e.key === 'Backspace' || e.key === 'Delete') {
        setTimeout(() => {
            const cursorPos = input.selectionStart;
            // 定位到光标前最近的可填充位置,避免光标跳位
            const prevFillableIdx = fillableIndices.findLast(idx => idx < cursorPos);
            if (prevFillableIdx !== undefined) {
                input.setSelectionRange(prevFillableIdx + 1, prevFillableIdx + 1);
            }
        }, 0);
    }
});

// 初始化输入框值
input.value = maskTemplate;

方案二:使用jQuery-Mask插件实现

如果项目已引入jQuery,可借助jQuery-Mask插件简化实现,自定义掩码规则即可:

<input type="text" id="entry-number" value="1234-56??-????-0987">

<script src="jquery.min.js"></script>
<script src="jquery.mask.min.js"></script>
<script>
$(document).ready(function() {
    const maskPattern = '1234-56AA-AAAA-0987';
    $('#entry-number').mask(maskPattern, {
        translation: {
            'A': {
                pattern: /[0-9]/,
                fallback: '?'
            }
        },
        maxlength: false,
        onKeyPress: function(cep, e, field, options) {
            // 计算已填充的数字数量
            const filledCount = cep.replace(/[^0-9]/g, '').replace(/1234560987/g, '').length;
            const totalFillable = maskPattern.match(/A/g).length;
            // 填满所有位置后阻止继续输入
            if (filledCount >= totalFillable) {
                e.preventDefault();
            }
        }
    });
});
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:15:34