过滤选择器:漏斗式筛查


文档摘要

2.3 过滤选择器:漏斗式筛查 过滤选择器的定义可以用一句话立起来:它不从零开始找人,只在上一刀切出的集合里继续筛人。前两节的刀法都能独立命中,本节的刀具则必须挂在已有选择器后面—— 里真正的海选是 , 只是在海选结果里留下头一名。理解这层"二次加工"的定位,比背每一个过滤器的名字重要得多。 本节摘要:过滤选择器分三族——位置族(first、last、eq、lt、gt、even、odd)按序号留人,内容族(contains、has、empty、parent)按文本与子孙留人,可见性族(visible、hidden)按渲染状态留人;另有 not 与 filter 兼任万能漏斗。

2.3 过滤选择器:漏斗式筛查

过滤选择器的定义可以用一句话立起来:它不从零开始找人,只在上一刀切出的集合里继续筛人。前两节的刀法都能独立命中,本节的刀具则必须挂在已有选择器后面——$('li:first') 里真正的海选是 li:first 只是在海选结果里留下头一名。理解这层"二次加工"的定位,比背每一个过滤器的名字重要得多。

本节摘要:过滤选择器分三族——位置族(first、last、eq、lt、gt、even、odd)按序号留人,内容族(contains、has、empty、parent)按文本与子孙留人,可见性族(visible、hidden)按渲染状态留人;另有 not 与 filter 兼任万能漏斗。

漏斗模型:位置族先上场

图:过滤选择器的漏斗式筛查

图:过滤选择器的漏斗式筛查

对着标本页把位置族跑一遍,重点体会"从零起算":

$('li').length; // 4 $('li').eq(1).text(); // 李四:eq 按集合内序号取人,从零开始 $('li:first').text(); // 张三 $('li:lt(2)').length; // 2:序号 0 和 1,张三与李四 $('li:even').length; // 2:偶数位是第 0、2 位,张三与王五

:even:odd 的"偶奇"指的是序号而非第几个——人类直觉里的"第一个"在序号上是零,这套反直觉从 C 语言一路传到了这里。

内容族:按文本与子孙筛人

// 找到文本里含"心悸"的条目——文本匹配是全文包含关系 $('.item:contains("心悸")').addClass('flag'); // 有急症标记类?不,:has 看的是"有没有匹配某选择器的后代" $('li:has(b)').length; // 含加粗子元素的条目数 // 空面板检测:排查渲染是否落空 $('#queue:empty').length; // 队列被清空时返回 1

:contains 的匹配是区分大小写的全文包含,参数加不加引号在 jQuery 3 均可,但老版本只认带引号的写法——老项目里见到 :contains("x") 别顺手把引号删了。.filter() 是内容族的万能替身,任何写不成选择器的条件都能写成函数:

$('.item').filter(function () { return $(this).data('vital') === 'mid'; // 生命体征为中等的患者 }).addClass('watch');

可见性族:渲染说了算

:visible:hidden 的判定依据容易想当然。jQuery 的规则是:元素只要占据布局空间就算可见——visibility: hidden 或完全透明仍算可见,而 display: none、宽高为零、或本身不在文档里才算隐藏:

$('.item:hidden').length; // 页面初始全可见,返回 0 $('#queue').hide(); $('.item:hidden').length; // 4:父元素藏起来,子元素全算隐藏

这族过滤器在"折叠面板只处理可见行"这类场景里出场率极高,但它每次判定都要读布局信息,在长列表上反复调用会拖慢页面——第 7 章的性能账本里会再算它一笔。

原生对照:一半通用地、一半是方言

位置与状态类过滤里,CSS 标准早已收编了一部分:first-childlast-childnth-child(n)checkeddisabled 在原生查询里全部合法。jQuery 方言(eqltgtcontainsvisible)则出不了 jQuery 的大门。对照着记:

需求 jQuery 写法 原生写法
第三个条目 $('li').eq(2) document.querySelectorAll('li')[2]
首个子元素 $('li:first') querySelectorAll('li > *:first-child') 或取集合首项
文本包含 $('.item:contains("心悸")') 无对应,需取集合后 filter 判断 textContent
已勾选 $('input:checked') querySelectorAll('input:checked'),两边通用

规律与上一节一致:通用语法放心混用,方言一律留在 jQuery 世界里。拿不准时最稳的办法是先用基础选择器拿到集合,再用 .filter() 收窄——语义清晰,两边都不踩线。

漏斗的方法族:not、is、slice、add

选择器形态的过滤器还有一批方法形态的兄弟,它们直接作用在 jQuery 集合上,与漏斗模型天然契合:

$('li').not('.done'); // 反向筛:排除已完成,等价 :not(.done) $('li').slice(1, 3); // 按序号切一段,含头不含尾 $('li').is('.urgent'); // 不筛人,只问是非:集合里有没有急症 $('#queue').children().add('#beds li'); // 两路结果并成一批

.is() 值得单说:它不返回集合、只返回布尔,是"这个集合里存在匹配项吗"的问诊句。委托处理器里判断"点中的是不是急症条目"、离开页面前判断"还有没有未保存项",都用它——比先 filter 再数 length 干脆,也比读 length 更符合语义。

病例:筛选次序写反,漏斗筛错人

背景:标本页要做"未完成患者里的前两条加急标"。一次会诊写了 $('li:lt(2):not(.done)'),结果页面有时正常、有时加急标落在已完成的患者头上。

操作排查:把两段漏斗拆开分别数——$('li:lt(2)') 恒定命中前两名,:not(.done) 在其后再筛。若前两名恰好已完成,最终结果为空;而当时页面渲染顺序在拖拽排序后是动态的,于是症状时隐时现。真正要的是先排除、再取前二$('li:not(.done):lt(2)')

结果与解读:交换次序后行为稳定。过滤选择器从左到右依次作用,每一节的漏斗都作用在左边剩下的集合上——"先收窄、再取位"的次序不可颠倒。这条规则在链条更长时更要紧:海选、排除、定位三段的最佳排序是把代价最大的海选放最左、最具体的条件放右侧收口。变式:若"未完成"要按数据字段判断而非类名,把 :not(.done) 换成 .filter() 函数即可,位置条件 :lt(2) 保持在链尾不动画——次序原则不因漏斗形态改变。

要点复盘

  • 过滤器不海选,只在上一个集合里二次筛人;$('li:first') 的主语是 li
  • 位置族全部从零起算,:even 指偶数序号位,不是"第偶数个"。
  • :has 看子孙、:contains 看文本、:empty 看子节点,三者别混。
  • 可见性以布局空间为准:visibility 隐藏不算隐藏,display 隐藏才算。
  • 万能漏斗是 .filter(fn),写不成选择器的条件都交给它。

常规元素的刀法已经齐全,下一节专攻一类特殊组织——表单控件,它们的"状态"比"位置"更值得筛。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U