应使用包裹筛选控件,而非;用FormData自动采集、form.elements遍历、submit事件校验;多维字段独立命名;动态添加用form.append();提交前过滤空值并同步URL。

用 <form></form> 包裹筛选控件,别用 <div>
<p>直接上手就错的点:很多人把筛选区域写成一堆 <code><div class="filter-item">,再靠 JS 手动收集值。结果加个新字段就得改 JS,name 拼错一个后端就收不到,刷新页面还丢状态。
<p>正确做法是用原生 <code><form id="filter-form"></form> 包住所有筛选项。这样:
-
new FormData(document.getElementById('filter-form')) 自动聚合所有已选值,checkbox 多选、select[multiple]、空值自动跳过
-
form.elements 可直接遍历控件,不用 querySelectorAll('[name]') 硬捞
- 配合
submit 事件,能自然触发校验(form.checkValidity())和防重复提交
多维字段要拆成独立 name,别合并或加方括号
new FormData(document.getElementById('filter-form')) 自动聚合所有已选值,checkbox 多选、select[multiple]、空值自动跳过form.elements 可直接遍历控件,不用 querySelectorAll('[name]') 硬捞submit 事件,能自然触发校验(form.checkValidity())和防重复提交name,别合并或加方括号比如你要筛「品牌 + 类别 + 价格区间」,后端接口期待的是 ?brand=apple&category=phone&price_min=100&price_max=500,前端就必须严格对应:
-
<input name="brand" type="checkbox" value="apple">(多个同名 checkbox 合法且必要) <select name="category"><option value="phone">手机</option></select>-
<input name="price_min" type="number">和<input name="price_max" type="number">—— 别用单个range或自定义data-price-range -
name="brand[]"是 PHP 风格,在纯 HTML/JS 场景下无效,FormData 不识别方括号
动态添加维度字段时,用 form.append() 而非 innerHTML
如果支持用户点击「+ 添加条件」来增加筛选维度(如再加一个「评分」或「发货地」),不要用 innerHTML += '...' 拼字符串——会丢失事件绑定、破坏表单语义、checkbox 状态无法被 FormData 采集。
立即学习“前端免费学习笔记(深入)”;
应该:
- 用
document.createElement()创建新控件 - 设好
name、type、value等属性 - 调用
form.append(newControl)插入到 form 内 - 新控件会自动纳入
FormData和form.elements范围
URL 同步和空值处理最容易被忽略
筛选状态不存 URL,用户分享链接或刷新就回到默认;空值没过滤,后端可能收到 ?brand=&category= 导致 SQL 错误或全量返回。
关键两步必须做:
- 提交前用
Array.from(formData.entries()).filter(([k, v]) => v)清掉空值 - 用
history.replaceState()把有效参数写进 URL:const url = new URL(window.location); url.search = filteredParams; history.replaceState(null, '', url)
否则看似功能跑通,一上线就被用户反馈“换个浏览器就失效”“发给别人看不了”。



















