前言
表单是前端业务占比最高的模块,新增、编辑、搜索弹窗全部离不开表单。很多同学只会简单判断非空,复杂联动、防重复提交、多字段联动、异步校验、错误聚焦处理经常踩坑。 本篇全部基于原生 JS+jQuery,不依赖任何 UI 组件库。
一、表单校验思路
- 基础校验:非空、长度、手机号、邮箱、数字范围
- 联动校验:A 输入框的值,影响 B 输入框是否显示、是否必填
- 异步校验:输入用户名,请求后端判断账号是否已存在
- 提交前整体校验,校验失败定位到第一个错误输入框
常用正则工具
js
运行
const Regs = { phone:/^1[3-9]\d{9}$/, email:/^\w+([.-]\w+)*@\w+([.-]\w+)*\.\w{2,}$/ }二、完整表单校验示例
html
预览
<div> <div> <label>用户名</label> <input type="text" id="username"> <span class="error"></span> </div> <div> <label>手机号</label> <input type="text" id="phone"> <span class="error"></span> </div> <button id="submitBtn">提交</button> </div>js
运行
//校验函数 function validateForm(){ let pass = true const username = $("#username").val().trim() const phone = $("#phone").val().trim() $(".error").text("") if(!username){ $(".error").eq(0).text("用户名不能为空") pass = false $("#username").focus() } if(!Regs.phone.test(phone)){ $(".error").eq(1).text("手机号格式错误") if(pass) $("#phone").focus() pass = false } return pass } //防重复提交:增加锁标记 let submitLock = false $("#submitBtn").on("click",async function(){ if(submitLock) return if(!validateForm()) return submitLock = true $(this).prop("disabled",true) try{ const params = { username:$("#username").val().trim(), phone:$("#phone").val().trim() } const res = await Request.post("/api/save",params) Component.toast("保存成功") }catch(err){ Component.toast("保存失败") }finally{ submitLock = false $(this).prop("disabled",false) } })三、表单高频业务场景
- 防重复提交:点击按钮加锁,接口请求完成解锁,防止连续点击多次发请求。
- 联动显隐:选择下拉框的值,控制其他表单项显示隐藏,同时动态修改是否必填。
- 异步校验:失去焦点 blur 的时候调用接口校验,不要每输入一个字符就请求接口,配合防抖。
js
运行
$("#username").on("blur",Utils.debounce(async function(){ const val = $(this).val().trim() if(!val) return const res = await Request.get("/api/checkUser",{name:val}) if(res.code!==200){ $(".error").eq(0).text("账号已存在") } },400))- 编辑回填:后端返回数据,循环赋值给表单,注意 null、undefined 空值处理。
四、表单踩坑总结
- input 获取值一定要 trim (),去除首尾空格。
- 异步校验不要写在 submit 里面,提交的时候只做同步校验。
- 一定要做提交锁,避免短时间多次提交。
- 校验失败自动 focus 定位到第一个错误输入,提升用户体验。
面试简答
Q:表单防重复提交有哪些方案?
- js 加锁,按钮置灰;
- 接口增加 token 令牌;
- 后端接口做幂等处理。
小结
中后台系统 70% 业务都是表单,把表单的各种边界处理做好,业务开发能力会直接上一个台阶。