校验函数应接收 htmlformelement 参数以支持复用;优先调用 input.checkvalidity() 复用浏览器原生校验;错误提示须绑定到具体 input 元素旁;异步校验需支持 abortcontroller 取消与防抖。

校验函数必须接收 HTMLFormElement 而非表单ID
硬编码 ID 会锁死复用场景,比如同一页面多个登录表单、或动态渲染的弹窗表单。直接传入 form 元素,既兼容 document.querySelector('form'),也支持事件回调里的 event.target。别写 validateFormById('login-form'),写 validateForm(form) —— 后者才能被 form.addEventListener('submit', e => { e.preventDefault(); validateForm(e.target); }) 直接调用。
required、email、minlength 等原生属性要优先读取
浏览器原生校验逻辑(如点击提交时自动高亮、checkValidity() 返回值)和你的 JS 校验必须对齐,否则用户看到「浏览器说合法,你的提示说不合法」就懵了。实操建议:
- 先调用
input.checkValidity(),它已内置对required、type="email"、minlength等的判断,别自己重复写正则 - 仅对原生不支持的规则(如「两次输入密码一致」「手机号归属地校验」)做额外检查
- 用
input.validationMessage获取浏览器默认提示文本,可直接透传给 UI,避免中英文混搭
错误信息必须绑定到具体 input 元素,而非全局弹窗
复用性差的典型表现:所有错误都塞进一个 div#error-summary。这会让用户找不到哪个字段错了,尤其在长表单或移动端上。正确做法是每个 input 旁动态插入/更新 span.error-message:
function showFieldError(input, message) {
let errorEl = input.parentNode.querySelector('span.error-message');
if (!errorEl) {
errorEl = document.createElement('span');
errorEl.className = 'error-message';
input.parentNode.appendChild(errorEl);
}
errorEl.textContent = message;
input.classList.add('invalid');
}
注意:务必用 input.parentNode 而非固定选择器,否则无法适配不同 DOM 结构(如有的表单用 div.form-group,有的用 td)。
异步校验(如用户名是否已存在)必须支持取消与防抖
用户快速输入时连续触发 5 次「用户名可用性检查」,不仅浪费请求,还可能因响应顺序错乱导致最终显示错误结果。关键控制点:
- 每次新请求前,用
AbortController中止上一次未完成的 fetch - 对
input的input事件加 300ms 防抖,避免每敲一个字就发请求 - 异步校验结果只覆盖对应字段状态,不影响其他字段的同步校验结果
- 失败时保留用户输入,仅更新错误提示;成功时清空该字段错误,但不要自动跳转或提交
真正难的不是写校验逻辑,而是让错误提示精准附着在字段生命周期里——DOM 存在时显示,移除时清理,重复渲染时不累积旧节点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











