用包裹筛选项,配合FormData和事件委托可快速构建可维护多条件筛选器;天然支持控件采集、空值过滤及校验,避免手动遍历埋雷。

直接用 <form></form> 包裹筛选项,配合 FormData 读取 + 原生事件委托,5 分钟内就能跑通一个可维护的多条件筛选器。别写一堆 document.getElementById 或手动拼对象,那是给自己埋雷。
为什么必须用 <form></form> 而不是 <div>
<p>不用 <code><form></form> 的后果很直接:你得自己遍历所有 input、判断 type、处理 checkbox 多选、过滤 disabled、跳过空值——稍一改动(比如加个动态渲染的品牌选项),name 漏了或拼错,整个采集逻辑就失效。
<form></form> 天然支持:
-
form.elements直接拿到所有控件,包括<select multiple></select>和未选中的radio -
new FormData(form)自动忽略未选中的checkbox,合并同名name(如多个brand),跳过disabled项 -
form.checkValidity()可配合required做基础校验,不用自己写正则
FormData 怎么安全转成筛选参数
别手动遍历 form.elements 再一个个取 .value。直接用 FormData,再转成标准键值对:
立即学习“前端免费学习笔记(深入)”;
const form = document.querySelector('#filter-form');
form.addEventListener('submit', e => {
e.preventDefault();
const formData = new FormData(form);
const params = Object.fromEntries(formData.entries());
// { brand: "apple", category: "phone", price_min: "100" }
});
注意点:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 多个同名
checkbox(如name="brand")被选中时,FormData默认只保留最后一个值;要获取全部,得用formData.getAll('brand') - 数值类字段(如
price_min)可能为空字符串,需显式判断:if (params.price_min !== "") { ... } - 后端若接收数组(如
?tag[]=vue&tag[]=react),前端必须用new URLSearchParams(formData)或手动构造,Object.fromEntries会丢数据
怎么避免“改两个框只响应最后一次”的竞态问题
每个输入框单独绑 input 或 change 事件没问题,但回调里不能各自执行一次完整过滤。用户同时改两个框,后触发的那个会覆盖前一个的结果。
必须统一收集、统一执行:
- 所有筛选控件共用一个回调函数,比如
onFilterChange() - 函数内一次性读取全部值:
const brand = form.brand?.value;或更稳妥地用new FormData(form) - 加防抖(
setTimeout/clearTimeout),尤其在input事件里,避免每敲一个字都重算 - 如果涉及 DOM 显隐,用
.hidden类切换而非style.display,防止丢失原始布局样式
data- 属性怎么设才不翻车
别用 class="tag-react" 做筛选依据——class 是样式语义,不是数据语义,容易误匹配、难维护、无法区分大小写。
正确做法是统一用 data- 属性标记真实值:
- 商品卡片写
<div class="product" data-brand="apple" data-category="phone" data-price="999"> <li>数值类务必用 <code>parseFloat(el.dataset.price)转类型,否则'100' 会返回 <code>true - 多值字段(如标签)用逗号分隔:
data-tag="vue,react,typescript",匹配时用el.dataset.tag.split(',').includes('vue') - 注意
dataset自动转小写:data-user-id→el.dataset.userid,命名避开驼峰冲突
最常被忽略的一点:空值容错。没写 data-brand 的元素,el.getAttribute('data-brand') 返回 null,不是空字符串,直接 === 会出错,得先做 ?? '' 或 || '' 处理。


















