兄弟选择器+first-of-type无法选中指定h3后首个ul的问题求解
DND术士专长列表按评分排序控制台解决方案
需求
将网页中不同等级对应的术士专长无序列表,按rating-blue>rating-green>rating-orange>rating-red的优先级重排序,原有列表默认按名称字母序排列。
原有代码问题
原有选择器使用#invocations-level-${level} + p + ul的直接相邻规则,匹配逻辑过于严格:
- 部分等级标题后存在广告span标签,无法匹配到对应ul
- 部分等级标题后无p标签,匹配直接失效
尝试使用~ ul:first-of-type也无法生效,因为:first-of-type默认匹配父元素下第一个同类型元素,会将当前等级之前的ul包含进匹配范围,导致后续等级匹配错误。
解决方案
使用CSS第四代选择器:nth-child(1 of <集合>)精准定位当前等级标题后的第一个ul元素,不受中间插入的p、广告span等标签影响,符合单选择器要求。
最终可运行代码
[1, 3, 5, 7, 9, 12, 15].forEach(level => { // 精准匹配当前等级对应的第一个ul const targetUl = document.querySelector(`#invocations-level-${level} ~ ul:nth-child(1 of #invocations-level-${level} ~ ul)`); if (!targetUl) return; // 按评分优先级重排列表 targetUl.innerHTML = ['blue', 'green', 'orange', 'red'] .flatMap(color => Array.from(targetUl.querySelectorAll(`li a.rating-${color}`))) .map(aNode => aNode.parentElement.outerHTML) .join(''); });
选择器原理解释
#invocations-level-${level} ~ ul:nth-child(1 of #invocations-level-${level} ~ ul)
#invocations-level-${level} ~ ul:匹配当前等级h3标题之后的所有兄弟ul元素:nth-child(1 of <集合>):从上述匹配的ul集合中取第一个元素,不受中间其他标签、其他元素类型的干扰
如果需要严格遵循原有代码的写法,完全使用$$拼接单选择器直接匹配a元素,可使用以下版本:
[1, 3, 5, 7, 9, 12, 15].forEach((level, index) => { $$('div#main-content > ul')[index].innerHTML = ['blue', 'green', 'orange', 'red'] .flatMap(colour => $$(`#invocations-level-${level} ~ ul:nth-child(1 of #invocations-level-${level} ~ ul) li a.rating-${colour}`)) .map(el => el.parentElement.outerHTML) .join(''); });
兼容性说明
上述选择器兼容Chrome 90+、Firefox 113+、Edge 90+版本,完全满足现代浏览器开发者控制台运行需求。
内容的提问来源于stack exchange,提问作者AncientSwordRage
相关产品推荐
相关产品推荐

