必须用 required + type + pattern 组合并绑定 submit 事件调用 reportValidity(),否则空白提交无法拦截;required 仅校验是否为空,不处理全角空格、零宽字符等;type="number" 填"123 "时 valueAsNumber 为 NaN;仅 e.preventDefault() 不触发原生校验;自定义规则需配合 setCustomValidity();FormData 值需清洗后再发送;后端必须独立校验,前端校验仅为体验优化。

必须用 required + type + pattern 组合,并绑定到 submit 事件中调用 reportValidity(),否则空白提交根本拦不住——哪怕写了 required,用户按回车或点按钮照样发空数据。
为什么加了 required 还会空白提交?
因为 required 只在表单真正提交(submit 事件)时触发校验,且只判断是否为空字符串或未选中状态,不看内容格式。常见错误现象:
- 用户输入全角空格、零宽字符(
u200b)或不间断空格(u00a0),required认为“有值”,实际后端收到的是不可见垃圾 -
type="number"的字段填了"123 "(尾部空格),required通过,但valueAsNumber是NaN - 用
<button type="button"></button>或内联onclick="return false"拦截,根本没触发submit事件,原生校验完全失效
submit 事件里不调 reportValidity() 就等于没校验
仅 e.preventDefault() 只是卡住刷新,不会弹提示、也不会检查字段是否合法。必须手动触发浏览器原生校验流程:
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
- 调
form.reportValidity():弹默认气泡提示,返回布尔值,适合快速落地 - 若需自定义 UI 提示,改用
form.checkValidity(),但得自己遍历form.elements,读element.validationMessage和element.validity.valueMissing等属性生成反馈 - 对自定义规则(如手机号、密码强度),必须配合
input.setCustomValidity("提示");校验通过后要立刻调input.setCustomValidity("")清空,否则后续checkValidity()永远返回false
FormData 拿到的值不能直接发,必须清洗后再序列化
new FormData(form) 返回的是原始 input.value,包括首尾全角空格、零宽字符等 trim() 都清不掉。正确做法是:
立即学习“前端免费学习笔记(深入)”;
- 先用
reportValidity()过一遍原生校验 - 再用
new FormData(form)构造数据 - 遍历转成对象后,对每个字符串字段显式清洗:
value.replace(/^[u2000-u206Fu2E00-u2E7F\'\’\‘\“\”\«\»\—\–\…\·\•\′\″\‹\›]+|[u2000-u206Fu2E00-u2E7F\'\’\‘\“\”\«\»\—\–\…\·\•\′\″\‹\›]+$/g, '')(比trim()更狠) - 特别注意
textarea:换行要保留,但服务端仍需过滤 XSS,前端清洗不等于安全
最易被忽略的一点:所有这些校验和清洗,都只是减少无效请求的体验优化。用户禁用 JS、用 curl 直接 POST、甚至浏览器开发者工具改 DOM,都能绕过全部逻辑。后端必须独立做空值判断、正则匹配、类型转换和长度限制——前端拦得再严,也不能少这一步。


















