如何仅用CSS选择器根据子元素属性选择列表中第二个启用按钮?
问题
假设有这样的HTML结构:
<ul> <li><button disabled/></li> <li><button disabled/></li> <li><button /></li> <li><button /></li> <li><button /></li> </ul>
里面禁用的按钮数量不确定,但肯定是连续排在启用按钮的前面。现在要选中第二个启用的button。
之前试的几个选择器都不好使:
- 用
"ul li:nth-of-type(2) button:not([disabled])":只会检查第二个<li>里的按钮有没有启用,如果这个按钮是禁用的,就找不到任何元素,没法定位到第二个启用的按钮。 - 用
"ul li button:not([disabled]):nth-of-type(2)":因为每个<li>里只有一个button,:nth-of-type(2)根本匹配不到东西。 - 本来想先把所有启用的button选出来再取第二个,比如写
"ul (li button:not([disabled])):nth-of-type(2)",但这种写法语法不对。
注:这个需求是用来写UI测试的,要找到React时间选择器里的第二个可用时间段。
解决方案
有两种可行的方式,看你测试环境支持哪种:
方式一:用CSS :has()选择器(推荐,逻辑清晰)
直接用下面这个选择器就能精准选中目标:
ul li:has(button:not([disabled])):nth-child(2) button
简单说下逻辑:
- 先筛选出所有包含启用状态button的
<li>; - 在这些筛选后的
<li>里挑第二个; - 最后定位到这个
<li>里的button,就是你要的第二个启用按钮。
方式二:环境不支持:has()时的替代方案
如果测试工具或浏览器不支持:has(),可以用下面两种办法:
方案1:相邻兄弟选择器
ul li button:not([disabled]) ~ li button:not([disabled])
这个选择器会找到第一个启用按钮后面的第一个启用按钮,也就是第二个启用的按钮——刚好符合题目里禁用按钮都在前面、启用按钮连续的条件。
方案2:用测试框架的API直接取
比如在Playwright或者Cypress里,先获取所有启用的按钮,再选第二个:
// Playwright示例 const enabledButtons = await page.$$('ul li button:not([disabled])'); await enabledButtons[1].click(); // 索引从0开始,第二个元素是索引1
// Cypress示例 cy.get('ul li button:not([disabled])').eq(1).click();
内容的提问来源于stack exchange,提问作者Preston Moore
相关产品推荐
相关产品推荐

