layui中需用keyup监听+定时器实现银行卡/身份证号防窥:输入后1–2秒仅最后一位显示●,其余可见,data-real-value存真实值;blur时全遮蔽;验证时读取data-real-value而非val。

layui 表单中如何给 input 添加防窥遮蔽(如银行卡号、身份证号)
layui 本身不提供原生的“防窥输入框”组件,但可以通过组合 input[type="text"] + 自定义遮蔽逻辑 + 键盘事件控制实现。核心思路是:用户每输入一位,显示真实字符 1–2 秒后自动替换为 ● 或 *,同时保留原始值供提交用。
为什么不能直接用 type="password"?
直接改 type="password" 会导致全字段不可见,无法校验格式(如身份证第17位奇偶性、银行卡号 Luhn 校验),且移动端软键盘会切换为数字/符号键盘,影响输入体验。更关键的是:它无法实现“部分可见 + 延迟遮蔽”这种兼顾安全与可用性的交互。
用 lay-keyup 和定时器手动实现遮蔽逻辑
在 layui 表单中,推荐监听 keyup(而非 input)并配合 setTimeout 控制遮蔽延迟。需注意:setTimeout 必须可清除,否则快速连输会导致多个定时器叠加,出现闪烁或遮蔽错乱。
- 给 input 添加
class="layui-input anti-peek"便于统一处理 - 用
data-real-value属性缓存未遮蔽的真实值(避免 DOM 操作污染) - 每次按键后清除上一个定时器:
clearTimeout(this.timer) - 延迟 1500ms 后执行遮蔽:将最后一位替换为
●,其余保持原样(如输入 “12345”,显示 “1234●”) - 焦点离开时(
blur)立即全部遮蔽,防止用户切走后信息残留
form.on('submit', function(data) {
// 提交前取 data.field['idcard'] 即可,它仍是原始值
console.log(data.field.idcard); // 如 "110101199003072958"
return true;
});
// 防窥初始化
$('.anti-peek').each(function() {
const $inp = $(this);
let timer = null;
$inp.on('keyup', function() {
clearTimeout(timer);
const val = $inp.val();
$inp.attr('data-real-value', val);
// 只遮蔽最后一位,其余可见
if (val.length > 0) {
$inp.val(val.slice(0, -1) + '●');
}
timer = setTimeout(() => {
$inp.val(val.slice(0, -1) + '●');
}, 1500);
}).on('blur', function() {
const real = $inp.attr('data-real-value') || '';
$inp.val(real.replace(/./g, '●'));
});
});
兼容性与边界问题必须处理
移动端长按粘贴、中文输入法、撤销(Ctrl+Z)、剪切(Ctrl+X)等操作会绕过 keyup,导致 data-real-value 不同步。稳妥做法是:在 input 事件后立即更新真实值,并在 blur 时用正则过滤非数字字符(如身份证中的 X)。
- 银行卡号建议只允许数字,用
val.replace(/\D/g, '')过滤 - 身份证号需保留末位
X,用val.replace(/[^0-9Xx]/g, '') - 不要依赖
placeholder显示示例,它可能被遮蔽逻辑干扰 - 如果表单启用了 layui 的
form.verify,验证函数里应读取$(elem).attr('data-real-value')而非$(elem).val()
真正难的不是加遮蔽,而是让遮蔽不干扰输入流、不破坏表单校验链、不被各种输入法和快捷键绕过——这些细节没处理好,防窥就只剩个样子。


















