讲解
表单是用户输入的主要入口。现代处理方式是拦截 submit 事件、event.preventDefault() 阻止默认跳转,然后用 FormData 一次性收集所有字段:new FormData(form).get('字段名') 取值,或 Object.fromEntries(new FormData(form)) 整体转对象。相比逐个 querySelector 读 value,FormData 代码量少一个数量级,还自动处理 checkbox、radio、多选。读取单个控件的值:文本框用 input.value,复选框用 checkbox.checked(布尔),单选组取被选中项的 value。
校验分两层:HTML 原生校验(required、type="email"、minlength、pattern 属性,浏览器自动拦截并提示,novalidate 可关闭)和 JavaScript 自定义校验(监听 submit 或 input 事件,手写规则,用 setCustomValidity 或自建提示展示错误)。实际项目通常两者结合:原生属性挡住低级错误,JS 处理复杂规则(两次密码一致、用户名校验接口)和自定义的提示样式。
提升体验的三个技巧:一、input 事件实时反馈(配合防抖,避免每次按键都发校验请求);二、提交中禁用按钮防重复提交——用户双击或网络慢时连点会发出多个相同请求;三、提交成功后 form.reset() 清空表单,失败时保留用户已填内容。文件上传用 input[type=file],从 fileInput.files 拿 File 对象,放进 FormData 后 fetch 提交。
示例
<form id="reg-form">
<input name="username" required minlength="3" placeholder="用户名" />
<input name="email" type="email" required placeholder="邮箱" />
<input name="password" type="password" required placeholder="密码" />
<label><input type="checkbox" name="agree" value="yes" /> 同意协议</label>
<button id="submit-btn" type="submit">注册</button>
</form>
const form = document.querySelector('#reg-form');
const submitBtn = document.querySelector('#submit-btn');
form.addEventListener('submit', async (event) => {
event.preventDefault(); // 阻止默认跳转
// FormData 一次收集所有字段
const data = Object.fromEntries(new FormData(form));
console.log('收集到:', data); // { username, email, password, agree? }
// 自定义校验
if (!form.querySelector('[name=agree]').checked) {
alert('请先勾选同意协议');
return;
}
// 防重复提交
submitBtn.disabled = true;
submitBtn.textContent = '提交中…';
try {
const response = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('注册失败');
form.reset(); // 成功后清空
alert('注册成功');
} catch (err) {
alert(err.message); // 失败时表单内容保留
} finally {
submitBtn.disabled = false;
submitBtn.textContent = '注册';
}
});
// 实时校验:输入时提示(防抖在定时器一章)
form.username.addEventListener('input', () => {
const ok = form.username.value.length >= 3;
form.username.style.borderColor = ok ? 'green' : 'red';
});
常见坑
- 按钮默认 type 是 submit:表单里的 不写 type 就会触发表单提交,想做普通按钮要写 type="button"。
- 用 click 监听提交:监听 submit 按钮的 click 会漏掉「输入框里按回车」提交的 path——永远监听 form 的 submit 事件。
- FormData 读不到未勾选的 checkbox:未勾选的复选框不会出现在 FormData 里,逻辑上用 'agree' in data 或 checked 判断。
- 提交后不防重:网络慢时用户连点产生重复订单/重复注册,禁用按钮 + 服务端幂等双保险。
小结
拦截 submit + preventDefault,FormData 收集字段;原生属性做基础校验,JS 做复杂规则;提交中禁用按钮防重。下一章进入强大的文本工具:正则表达式。