如何使用Javascript从CSS选择器字符串中删除所有伪选择器?

如何使用Javascript从CSS选择器字符串中删除所有伪选择器?,javascript,regex,string,css-selectors,pseudo-class,Javascript,Regex,String,Css Selectors,Pseudo Class,对于我正在执行的脚本,我需要验证DOM中是否存在CSS选择器。我想知道如何使用通用规则处理多个:伪选择器 像这样的事情很简单: var selector = "div.foo div.bar:active" 这可以由 selector.split(":").shift(); // > div.foo div.bar 但当我有多个选择器时,我不知道如何删除它们。大概是这样的: var selector = "div.foo:hover div.bar:after" 问题: 如何删除所有

对于我正在执行的脚本,我需要验证DOM中是否存在CSS选择器。我想知道如何使用通用规则处理多个:伪选择器

像这样的事情很简单:

var selector = "div.foo div.bar:active"
这可以由

selector.split(":").shift(); // > div.foo div.bar
但当我有多个选择器时,我不知道如何删除它们。大概是这样的:

var selector = "div.foo:hover div.bar:after"
问题:
如何删除所有CSS伪选择器:字符串中的某些内容?

您可以使用正则表达式删除它们并替换:

那个::?表示一个或两个冒号[您也可以将其写为:{1,2}],以处理::after等

这在大多数情况下都适用,但是如果您有非常复杂的伪代码,其中包含嵌套的伪代码,比如foo.bar:not.baz:active,那么您需要一个实际的CSS选择器解析器来正确处理它们。虽然您可能会构建一个regex替换,它将处理一位嵌套,但理论上可以有多个嵌套,这就是解析器的作用

但请注意,其中一些伪元素确实会影响选择的元素,例如:nth child,因此,如果您的目标是查看DOM中是否存在匹配的元素,则不希望删除这些元素。因此,您可能希望采取相当务实的方法,在一系列备选方案中列出要删除的内容,例如:

var toRemove = /:hover|:active|:before|:after|::?before|::?after|:and-so-on/g;
// ...
selector = selector.replace(toRemove, '');

没有那么多,它消除了删除第n个孩子行中重要结构选择器的机会。

删除所有伪选择器不会解决您的问题

举个例子:

p:first-child {}

<div>
    <div></div>
    <p></p>
</div>
由于段落不是第一个子项,除非DOM发生更改,否则不会是第一个子项,因此从选择器中删除:first-child将给出一个假阳性匹配

您只需要删除以鼠标或键盘交互和psuedo元素为条件的伪类。然后您需要使用特殊情况:link和:visted,以便匹配链接锚定,而不是不使用[href]属性选择器替换它们的锚定,这是一种稍微幼稚的方法,但对于所有实际用途来说应该足够好

您还需要决定:启用和:禁用。它们不会因用户交互而改变,但如果您计划使用JS切换它们,则可能需要删除它们


因为这里有很多条件,所以我要为它编写一个函数,而不是尝试一个简单的正则表达式

所以您只需要div.foo string.Nice。找到我要找的东西。谢谢另外,我知道这只是一个例子,但有趣的是,虽然foo.bar:not.baz:active在本文撰写时当前不是有效的CSS,但它将出现在选择器4中:not目前不接受单独的伪类:not:active,所以这仍然是您必须担心的事情。@T.J.Crowder-既然您提到CSS选择器解析器。。。您知道在浏览器环境中可用的浏览器吗?目前我正在使用,这似乎没有维护。谢谢@常客:我不知道,不知道,但是很受欢迎。这是一个NodeJS模块,因此它将假定为一个完全ES5环境,但我没有立即看到它使用了很多NodeJS特定的API调用,我只是浏览了一下,所以您可以在浏览器环境中使用它,只要浏览器具有相关的ES5功能,直接或通过垫片。Ok。我去看看。再次感谢!仅供参考,虽然很幼稚,但a:link、a:visted和a[href]在HTML中确实是完全等效的。至于:enabled和:disabled,您还必须考虑这样一个事实,即某些元素永远不会与这两个元素中的任何一个匹配——这些元素没有启用/禁用的概念,例如非表单元素。
p:first-child {}

<div>
    <div></div>
    <p></p>
</div>