不能信,只当它是个“格式提醒器”。type="email"校验极宽松,不查域名真实性、不拦零宽空格、不转idn,必须配合trim、正则锚定及后端专业库二次验证。

input type="email" 能信多少?
不能信,只当它是个“格式提醒器”。浏览器对 type="email" 的校验非常宽松:允许 me+tag@gmail.com,但拒绝 "john@doe"@example.com;接受 admin@mail.example(子域名),却可能放过 hello@world(缺顶级域)——尤其在旧版 Chrome 中。它不查 MX 记录、不发验证邮件、不转 IDN 域名(如含中文的邮箱必须先转成 xn--zr8h@xn--fsq097e.cn)。真正拦不住 test@.com 或 user@@example.com 这类明显错误,更拦不住粘贴进来的零宽空格(U+200B)。
pattern 正则怎么写才不白配?
直接写 pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}" 是错的——没加锚点,会导致 abc123@test.com456 也被放过。必须用 ^ 和 $ 锁死首尾:
pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
还要注意:
- 大小写敏感:HTML 的
pattern默认区分大小写,A-Z必须显式写出 - 不支持 Unicode 域名:像
张三@例子.中国会失败,得靠 JS 预处理转 Punycode -
title属性只在验证失败时显示,且无法覆盖浏览器默认提示,真要自定义文案得用setCustomValidity()
为什么 required + type="email" 还能提交空格?
因为原生验证不自动 trim()。用户输入 " user@example.com "(首尾带空格),checkValidity() 可能返回 true,但后端解析时大概率失败;而输入 " "(纯空格),部分浏览器认为“非空”,绕过 required 校验。
解决办法是手动清理再校验:
const emailInput = document.querySelector('input[type="email"]');<br>emailInput.addEventListener('blur', () => {<br> emailInput.value = emailInput.value.trim();<br> if (!emailInput.checkValidity()) {<br> emailInput.reportValidity();<br> }<br>});
关键点:
- 监听
blur而非input,避免过度触发 - 必须先
trim()再调checkValidity(),顺序不能反 - 调用
reportValidity()才会弹出气泡提示(Firefox 不自动滚动到字段)
前端验证到底该做到哪一步?
做到“快速反馈、降低误输率”就够了。比如拦截明显非法格式(缺 @、双 @@、无点号)、过滤不可见字符、统一 trim,这些能挡住 80% 的手误。但别试图用正则穷举 RFC 5322 全部规则——既做不到,也没必要。真正要卡住的点,比如邮箱是否已注册、是否为临时域名(如 @10minutemail.com)、MX 记录是否存在,全得交由后端用专业库(如 Python 的 email-validator)完成。最常被忽略的是:用户从微信/钉钉粘贴邮箱时,可能混入富文本残留或零宽字符,前端不清理,后端一解析就报错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











