pattern仅在提交时校验,无法实时限制输入;真正限制需用input事件+正则清洗并手动维护光标位置;末位校验码、15位升位、粘贴清洗等必须js实现。

用 pattern 属性做前端基础校验,但别指望它拦住所有错误
HTML 原生 input 标签无法直接“限制输入”,只能靠 pattern 配合 title 在表单提交时提示格式错误。它不阻止用户粘贴、输入非法字符,也不实时过滤——这是常见误解的源头。
实际做法是:给 <input type="text" pattern="[0-9Xx]{17}[0-9Xx]" title="请输入18位有效身份证号">,但注意这个正则只是粗筛(比如不校验末位校验码、不区分 15 位老号码),且 Safari 对 pattern 的支持在某些版本中会静默失效。
-
pattern只在调用checkValidity()或表单 submit 时触发,输入过程中完全无感 - 用户粘贴 “11010119900307299X” 这样的合法字符串没问题;粘贴 “11010119900307299Y” 会在提交时报错
- 移动端软键盘不会因
pattern自动切为数字键盘,需额外加inputmode="numeric"(兼容性尚可,但 iOS 旧版不支持)
用 input 事件 + 正则实时过滤,但得小心光标跳变
真正“限制输入”的逻辑必须靠 JS 监听 input 事件,对 value 做清洗。核心不是“禁止输入”,而是“输入后立刻修正”。否则用户打字时会发现光标乱跳、删不掉字符——这是最常被忽略的坑。
关键点在于:不能直接 el.value = newValue,而要用 setSelectionRange 保留光标位置。尤其当用户在中间插入或删除时,原生赋值会把光标重置到末尾。
- 先用正则
/^[0-9Xx]{0,18}$/允许最多 18 位,且只含数字和大小写 X - 每次输入后,截取前 18 位再替换非法字符:
value.replace(/[^0-9Xx]/g, '').slice(0, 18) - 修正后立即调用
el.setSelectionRange(pos, pos),其中pos要根据删除/插入动作动态计算(简单场景可用el.selectionStart记录原始位置)
校验末位校验码必须用 JS,HTML 做不了
18 位身份证的第 18 位是根据前 17 位算出的校验码,规则固定(加权求和 mod 11 查表)。这个逻辑 HTML 完全无法表达,pattern 更不可能覆盖。
必须在失去焦点(blur)或提交前,用 JS 跑一遍校验函数。常见错误是只校验长度和字符,却放过了 “110101199003072999” 这种明显错误的号码(末位应为 X)。
- 校验函数要区分大小写:X 和 x 都合法,但不能是其他字母
- 15 位老身份证需先升位(补‘19’年份 + 末位校验码),不能直接拒绝
- 建议把校验逻辑封装成独立函数,例如
isValidIdCard(value),返回布尔值,便于复用和测试
移动端软键盘适配和粘贴行为要单独处理
用户长按粘贴身份证号时,input 事件可能只触发一次,但内容已含空格、短横线甚至换行符。单纯依赖 input 事件过滤会漏掉这些。
更稳妥的做法是监听 paste 事件,同步阻止默认行为,提取纯文本后再清洗赋值,并手动恢复光标。
- 在
paste回调里调用event.preventDefault() - 用
event.clipboardData.getData('text')拿到剪贴板内容,再.replace(/[\s\-]/g, '')清除干扰字符 - 处理完后调用
el.focus()并设置光标位置,否则用户无法继续输入 - 别忘了同时监听
compositionstart/compositionend,避免中文输入法下出现半角/全角混输问题
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











