pattern 属性仅在表单提交时触发校验,input、blur 等事件不生效;需手动监听事件并调用 reportValidity() 实现实时反馈,且必须配 title 才显示错误文案。

pattern 属性只在 submit 时触发,blur 或 input 事件里不生效
很多人以为给 <input type="tel"> 加了 pattern 就能实时拦截非法输入,结果发现用户随便输“abc123”也能一直敲——因为 pattern 是表单级校验,只在调用 form.submit() 或点击原生提交按钮时才检查,input、blur、change 都不会触发提示。
真正需要实时反馈(比如输错立刻标红),必须自己监听 input 或 blur 事件,用 JS 做正则匹配 + 手动调用 reportValidity()。
-
pattern的正则不用写^和$,浏览器默认全匹配;写成pattern="[0-9]{11}"就行,别写pattern="^[0-9]{11}$" -
title必须配,否则 Chrome 不显示错误文案,Safari 显示但可能被截断 - 空值不走
pattern校验,只走required;所以 “输入 abc” 和 “什么都不输” 是两种校验路径
inputmode="numeric" 比 type="tel" 更可靠地唤起数字键盘
仅靠 type="tel" 在部分 Android 定制系统(如华为 EMUI、小米 MIUI)上仍会弹出带字母的键盘;而 inputmode="numeric" 是更底层的指令,告诉浏览器“只预期数字”,兼容性虽略低(iOS 12.2+、Android 7.0+),但在新设备上触发纯数字键盘的成功率更高。
稳妥做法是两者共存:<input type="tel" inputmode="numeric">,旧设备 fallback 到 type="tel",新设备优先响应 inputmode。
立即学习“前端免费学习笔记(深入)”;
- 别用
inputmode="tel"——该值未被主流浏览器支持,写了等于白写 -
inputmode="numeric"不影响语义或无障碍,它只管键盘;type="tel"才负责 screen reader 读作“电话号码” - 如果业务允许,可对关键字段(如注册手机号)加
autofocus,让用户一进页面就聚焦到数字键盘
JS 校验时直接 value = value.replace() 会破坏光标位置
在 input 事件里写 event.target.value = event.target.value.replace(/[^0-9]/g, '') 看似能过滤非数字,但会导致光标跳到末尾——用户想在中间删一个字符,结果光标跑到最后,体验极差。
正确做法是:先记录当前 selectionStart 和 selectionEnd,执行替换后,再用 setSelectionRange() 把光标恢复到合理位置。简单场景下,也可改用 beforeinput 事件(但 iOS Safari 不支持,得降级处理)。
- 粘贴内容(
paste事件)也要单独处理,不能只监听input - 中文输入法下输数字(如拼音模式打“yi”再选“1”)会产生合成事件,需监听
compositionstart/compositionend避免误删 - 正则别只认
1[3-9]\d{9},170/171/166/199/145/189 等号段已商用,建议用运营商号段库或至少放宽到^1[3-9]\d{9}$
国际化号码处理必须前后端独立清洗,前端不能信 pattern
pattern 写成 ^\+?[0-9\s\-\(\)]{7,15}$ 看似能覆盖国际格式,但实际提交时后端收到的可能是 “+86 (138) 1234-5678”,而真实验证要归一化为 E.164 格式(如 +8613812345678)。前端做格式化只是辅助,不能替代后端清洗。
- 前端可展示示例格式(如
+86 138 1234 5678),但要用aria-describedby关联说明文字,别塞进placeholder -
type="tel"对+、空格、括号、短横线完全放行,checkValidity()永远返回true,别被它骗了 - 服务端必须用 libphonenumber 类库解析并验证,不能只靠正则——号段变更、国家区号增减、NANP 区域调整都会让前端正则过期



















