层级选择器:沿血络追索


文档摘要

2.2 层级选择器:沿血络追索 不是每个目标都自带名牌——页面里大量元素既没有 ID 也没有专属类名,它们只是"某个已知元素旁边的那一个"。上一节的刀法靠元素自身特征命中,这一节换一条路:从已知锚点出发,顺着父子兄弟的血络走过去。四种层级走法是 jQuery 选择器里语法最简、最容易写错的部分,本节把它们一次厘清。 本节摘要:层级选择器共四条路线——空格找全部后代、大于号只找直接子代、加号找紧邻的下一个兄弟、波浪号找身后所有同辈兄弟。它们描述的是"元素之间的关系",真正的命中范围永远由锚点和关系共同决定。 四条血络:语法与语义 在标本页上,这四行的命中数分别是 4、4、2、2。

2.2 层级选择器:沿血络追索

不是每个目标都自带名牌——页面里大量元素既没有 ID 也没有专属类名,它们只是"某个已知元素旁边的那一个"。上一节的刀法靠元素自身特征命中,这一节换一条路:从已知锚点出发,顺着父子兄弟的血络走过去。四种层级走法是 jQuery 选择器里语法最简、最容易写错的部分,本节把它们一次厘清。

本节摘要:层级选择器共四条路线——空格找全部后代、大于号只找直接子代、加号找紧邻的下一个兄弟、波浪号找身后所有同辈兄弟。它们描述的是"元素之间的关系",真正的命中范围永远由锚点和关系共同决定。

四条血络:语法与语义

$('#ward li'); // 后代:ward 之内所有 li,无论嵌套多深 $('#queue > li'); // 子代:queue 的直接子级 li,孙辈不算 $('.urgent + li'); // 相邻:紧跟在 urgent 后面的那一个 li $('.urgent ~ li'); // 兄弟:urgent 身后所有同辈 li

在标本页上,这四行的命中数分别是 4、4、2、2。看起来"后代"与"子代"结果相同,只因为标本页只有一层嵌套——一旦队列里出现嵌套列表,两者立刻分道扬镳:

<ul id="queue"> <li class="item urgent">张三 · 心悸</li> <li class="item stable">李四 · 扭伤</li> <li class="item stable">王五 · 复诊 <ul> <li class="item">王五的陪护登记</li> <!-- 嵌套了一层 --> </ul> </li> </ul>

此时 $('#queue li') 命中 4 个(陪护登记也算后代),$('#queue > li') 命中 3 个(陪护登记是孙辈)。**写后代空格之前先问自己:我要不要孙辈?**这一问能避开大半误伤。

图:四条层级路线的命中示意

图:四条层级路线的命中示意

组合刀谱:从锚点走到目标

层级刀真正的威力在于串联。几个实战频率最高的组合:

// 场景一:队列里紧跟在急症后面的那个普通患者——相邻刀 $('.urgent + .item').text('请这位患者先到二号诊室'); // 场景二:清空主队列的所有直接条目——子代刀保证不动嵌套内容 $('#queue > li').removeClass('urgent stable done'); // 场景三:只想要主面板里的标题,别处的 h2 不许动——后代链 $('#ward .panel-title').addClass('active'); // 场景四:按钮的兄弟全部禁用——兄弟刀 $('#topbar .btn ~ button').prop('disabled', true);

读组合时从右往左翻译更顺:$('#queue > li') 是"选出那些父元素恰为 queue 的 li",右侧永远是最终目标,左侧是它的身世证明。

与原生对照:语法相通,方言不同

四条层级路线在原生 querySelectorAll 里语法完全一致,语义也一致——它们本来就是 CSS 选择器。真正的分岔在"方言"上:jQuery 在层级之外还有一批自造的过滤写法((':first')(':eq(2)')(':parent') 这类),它们不是 CSS 标准,原生查询不认识:

$('#queue li:first'); // jQuery:第一个 li,正常工作 document.querySelectorAll('#queue li:first'); // 报错:非法选择器 document.querySelectorAll('#queue li:first-child'); // 合法:这是 CSS 标准

习惯把 jQuery 选择器整体粘给原生查询的代码,会在这里翻车。规律很好记:冒号后面是英文单词的常见形态且 CSS 里背过的(first-childnth-of-typechecked),两边通用;冒号后面带括号参数或明显是缩写的(eqltgtvisible),是 jQuery 方言。

四刀对照表:方向与边界

路线 语法 行走方向 边界规则
后代 A B 向下穿透所有层 只要血缘上在 A 之内,隔多少层都算
子代 A > B 向下只看一层 父亲必须恰是 A 本人,祖父是 A 不算
相邻 A + B 向后看一位 只认紧邻的那一个,中间隔着注释以外的节点就失配
兄弟 A ~ B 向后看全部 身后所有同辈 B,身前的不算

表里最反直觉的是相邻刀的"紧邻"二字:A + B 要求 B 紧跟在 A 之后,若两者之间插进一个换行渲染的文本节点无妨,但插进任何别的标签就再也不匹配。所以给"下一个"这类需求写选择器前,最好先确认中间没有别的元素——不然一改版式选择器就静默失明。

病例:改版后全线失明的层级链

背景:标本页的侧栏原本结构是侧栏、面板、标题三层,样式脚本用 $('#sidebar > .panel > h3') 批量加了下划线。改版时设计师在面板外面套了一层卡片容器,页面一上线,下划线全没了。

操作排查:先数命中——console.log($('#sidebar > .panel > h3').length) 打出零,说明不是样式被覆盖,是根本没选中。逐层验证:$('#sidebar > .panel') 命中为零,而 $('#sidebar .panel') 命中正常。结论:面板不再是侧栏的直接子代,两层子代刀断了一环。

修复与解读:这类需求的稳定写法是"锚点用 ID 保命,中间层用后代空格放宽"——改成 $('#sidebar h3') 或至少 $('#sidebar .panel h3'),把对中间层级的依赖降到最低。层级链写得越深,对文档结构的要求越苛刻,结构微调一次就全线失明;层级选择器的工程原则是够用即可,宁浅勿深。变式:如果标题在页面别处也会出现、不能放宽到整个侧栏,就给面板一个稳定类名做锚,用 .panel-title 这类语义类替代结构位置——能用语义命名的目标,就别用位置关系硬算。

要点复盘

  • 四条路线:空格全部后代、大于号直接子代、加号紧邻下一个、波浪号身后全部;兄弟刀只向身后看。
  • 空格与大于号的分水岭是"要不要孙辈",写之前先确认。
  • 组合选择器从右往左读:右侧是目标,左侧是身世。
  • 层级语法与 CSS 原生一致;firsteq 这类 jQuery 方言不能喂给原生查询。
  • 目标越是没有名牌,越要先找一个稳定的锚点,再用关系走过去。

能沿关系走了还不够快,下一节给刀装上漏斗——在已有集合里按位置、内容、可见性二次筛人。


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