pattern属性仅在表单提交或调用reportValidity()时触发原生校验,不实时拦截输入;真正阻止非法输入需监听input事件并用正则清洗字符串。

pattern 属性只在 submit 时生效,别指望它实时拦
用 pattern="^[1-9]\d*$" 配合 type="text",表单提交时会触发浏览器原生校验,但用户输入过程中完全无反应——粘贴 abc、输 -5 或 0123 都能照常显示,value 不变,也不自动清空。只有调用 form.reportValidity() 或点击 submit 按钮时才弹提示。它不拦截、不过滤、不修正,纯属“事后追责”。
input 事件 + 正则清洗才是真拦截
要真正阻止非正整数输入(包括粘贴、拖拽、中文输入法下误输),必须监听 input 事件,而非 keydown(后者捕获不到粘贴)。核心逻辑分两步:
- 用
/[^0-9]/g删掉所有非数字字符 - 再用
/^0+/去除前导零(正整数不能以0开头,0本身也不合法)
示例代码:
input.addEventListener('input', e => {
let v = e.target.value;
v = v.replace(/[^0-9]/g, '');
v = v.replace(/^0+/, '');
if (v !== e.target.value) {
e.target.value = v;
}
});
type="number" + min="1" + step="1" 能拦住什么
这个组合能触发移动端数字键盘,且在 submit 或 reportValidity() 时强制校验:值必须是 ≥1 的整数。但它不干预输入过程——value 可能为空、为 "-5"、"3.14" 或 "abc",此时 valueAsNumber 是 NaN。关键限制:
立即学习“前端免费学习笔记(深入)”;
-
min="1"和max只在表单校验阶段起作用 -
step="1"必须显式写,否则默认允许小数(如2.5)通过 -
pattern对type="number"完全无效,浏览器直接忽略
为什么不用 parseInt / Number 判断再还原
有人想先 parseInt(v),再比对 String(result) === v,这看似严谨,但实际踩坑:
-
parseInt("0123")→123,但字符串仍是"0123",比对失败,误判为非法 -
parseInt("123abc")→123,又会把脏输入当成合法 - 无法处理光标位置,用户在中间修改时容易跳位或删错
所以,**正则清洗字符串本身,比解析再比对更直接、更可控、更少歧义**。真正难的不是写正则,而是处理粘贴后光标偏移和中文输入法下的组合字符——这些细节一旦漏掉,体验就断层。



















