静态页多条件筛选应使用包裹控件并用FormData读取,数据≤1000行可前端实时过滤,需统一防抖、精确匹配、.hidden类控制显隐,避免DOM遍历错误和display误设。

静态页做多条件筛选,本质是用 JavaScript 驱动 DOM 显隐,不是靠 HTML 自己“筛选”。数据量 ≤1000 行时,前端实时过滤完全可行;超过就得切后端分页,否则卡死。
必须用 包裹筛选控件,别用
不用 的后果很直接:你得手动遍历每个 、判断 type、处理 checkbox 多选、拼 query string——DOM 一改,JS 就断。而 天然支持:
-
form.elements 直接拿到所有控件,包括 和未选中的 checkbox
-
new FormData(form) 自动忽略未选中的 checkbox、合并同名 name(如多个 brand)、跳过 disabled 项
-
form.checkValidity() 可配合 required 做基础校验,不用自己写正则
常见错误: + document.querySelectorAll('[name]') 硬捞——一旦加个动态渲染的筛选项,name 漏了或拼错,整个采集逻辑就失效。
FormData 读取值时注意空值和多选
用户没填的字段,FormData 依然会返回空字符串,不是 undefined;多个同名 checkbox 被选中时,FormData.entries() 会返回多条记录,不是数组。
- 用
Object.fromEntries(formData.entries()) 得到的是单值对象,同名多选会被后一个覆盖
- 需要多选语义(如
brand=apple&brand=samsung),得用 Array.from(formData.entries()) 手动归类
- 价格区间这种成对字段(
price_min/price_max)要显式判断是否非空:if (params.price_min !== "" && params.price_max !== "") { ... }
-
name="brand[]" 是 PHP 风格,在纯 HTML/JS 场景下无效,FormData 不识别方括号
前端实时过滤时,所有条件必须在一个 filter 回调里合并
链式 .filter().filter() 或嵌套 if 容易漏行或错显:中间某次过滤把行筛没了,后续条件就无从判断;嵌套 if 容易写成“满足任一”而非“全部满足”。
- 正确做法:遍历每行
,对每个条件单独计算布尔值,再用 && 连接
- 每个条件默认返回
true(即不限制),避免空输入导致整行被隐藏
- 精确匹配建议清洗文本:
const clean = str?.trim().replace(/[\s\uFEFF\xA0]+/g, ' '),再用 === 比对,比 includes 更可控
- 只遍历
下的 ,不碰 或 ,避免误操作
显隐控制别碰 style.display,用 .hidden 类统一管理
直接设 el.style.display = "none" 再恢复,会丢失原始 display 值(比如原来是 inline-flex,恢复成 block 就错位);移动端频繁触发重排,滑动卡顿明显。
- 推荐 CSS 方案:
.item.hidden { opacity: 0; pointer-events: none; transition: opacity 0.2s; }
- JS 里只做一件事:
el.classList.toggle("hidden", !matches)
- 这样既不破坏文档流,动画自然,也不影响已绑定的事件监听器
- 初始化时统一给所有待筛选项加
.hidden,点击筛选时只对匹配项移除该类
最易被忽略的是:多个输入框共用一个防抖后的统一过滤回调,而不是每个 input 单独绑事件执行一次完整过滤——否则用户同时改两个框,后触发的那个会覆盖前一个的结果。
不用 的后果很直接:你得手动遍历每个 、判断 type、处理 checkbox 多选、拼 query string——DOM 一改,JS 就断。而 天然支持:
-
form.elements直接拿到所有控件,包括和未选中的checkbox -
new FormData(form)自动忽略未选中的checkbox、合并同名name(如多个brand)、跳过disabled项 -
form.checkValidity()可配合required做基础校验,不用自己写正则
常见错误: 用户没填的字段, 链式 直接设 最易被忽略的是:多个输入框共用一个防抖后的统一过滤回调,而不是每个 document.querySelectorAll('[name]') 硬捞——一旦加个动态渲染的筛选项,name 漏了或拼错,整个采集逻辑就失效。
FormData 读取值时注意空值和多选FormData 依然会返回空字符串,不是 undefined;多个同名 checkbox 被选中时,FormData.entries() 会返回多条记录,不是数组。
Object.fromEntries(formData.entries()) 得到的是单值对象,同名多选会被后一个覆盖brand=apple&brand=samsung),得用 Array.from(formData.entries()) 手动归类price_min/price_max)要显式判断是否非空:if (params.price_min !== "" && params.price_max !== "") { ... }
name="brand[]" 是 PHP 风格,在纯 HTML/JS 场景下无效,FormData 不识别方括号前端实时过滤时,所有条件必须在一个
filter 回调里合并.filter().filter() 或嵌套 if 容易漏行或错显:中间某次过滤把行筛没了,后续条件就无从判断;嵌套 if 容易写成“满足任一”而非“全部满足”。,对每个条件单独计算布尔值,再用 && 连接
true(即不限制),避免空输入导致整行被隐藏const clean = str?.trim().replace(/[\s\uFEFF\xA0]+/g, ' '),再用 === 比对,比 includes 更可控 下的
,不碰 或
,避免误操作
显隐控制别碰
style.display,用 .hidden 类统一管理el.style.display = "none" 再恢复,会丢失原始 display 值(比如原来是 inline-flex,恢复成 block 就错位);移动端频繁触发重排,滑动卡顿明显。
.item.hidden { opacity: 0; pointer-events: none; transition: opacity 0.2s; }
el.classList.toggle("hidden", !matches)
.hidden,点击筛选时只对匹配项移除该类input 单独绑事件执行一次完整过滤——否则用户同时改两个框,后触发的那个会覆盖前一个的结果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











