I need to get all DOM elements within DOM element myRootElement
, that satisfy the following conditions:
我需要获取DOM元素myRootElement中满足以下条件的所有DOM元素:
- have one of several element names (e.g.
div
or blockquote
)
- have one of several class names (e.g.
foo
or bar
)
If it were just condition 1, I know I can write:
如果这只是条件1,我知道我可以写:
let elementsWithRightName = myRootElement.querySelectorAll("div, blockquote");
and then I can filter the result, like so:
然后我可以过滤结果,如下所示:
let isOfNiceClass = (elem) => ["foo", "bar"].includes(elem.className);
let elementsOfInterest = [...elementsWithRightName].filter(isOfNiceClass);
but is there a better/most elegant/idiomatic way to apply both filters?
但是,有没有更好的/最优雅的/惯用的方法来同时应用这两种过滤器呢?
更多回答
myRootElement.querySelectorAll("div.foo, div.bar, blockquote.foo, blockquote.bar")
?
MyRootElement.querySelectorAll(“div.foo,div.bar,lockqute.foo,lockqute.bar”)?
@Kosh's hit the spot. Also, don't use .includes()
with .className
. Use .matches()
: ['foo', 'bar'].some(c => elem.matches(`.${c}`))
.
@Kosh一针见血。此外,不要将.Includes()与.ClassName一起使用。Use.matches():[‘foo’,‘bar’].Some(c=>elem.matches(`.${c}`))。
@Kosh: Hmm. Now suppose I have 100 element names and 100 class names. Shall I construct the 10,000-phrase string?
@Kosh:嗯。现在假设我有100个元素名和100个类名。我要构建10,000个短语的字符串吗?
@InSync: 1. Don't you mean some()
rather than every()
? 2. Are you making this suggestion for the case of a more complex rule regarding classes, that would require a regex? e.g. "class name starts with foo"? Or - is it because the class name itself is a comma-separated string?
@InSync:1.你的意思不是有些()而不是每个()吗?2.你的建议是为了处理关于类的更复杂的规则,这需要一个正则表达式吗?例如“类名以foo开头”?还是因为类名本身是逗号分隔的字符串?
1. Yes, I did mean .some()
. Fixed. 2. .className
is space-separated. You don't want to match <div class="food">
, do you? For more complex cases, I'd say that depends.
1.是的,我的意思是。修好了。2.类名称以空格分隔。您不想匹配,是吗?对于更复杂的案例,我会说这要视情况而定。
优秀答案推荐
Use .matches()
:
使用.matches():
classNames.some(c => elem.matches(`.${c}`))
Or, with the new-ish :is()
/:where()
:
或者,使用新的-ish:is()/:,其中():
const tags = ['div', 'blockquote'];
const classes = ['foo', 'bar', 'baz'];
const selector = `:is(${tags.join(', ')}):is(${classes.map(c => '.' + c).join(', ')})`;
// ':is(div, blockquote):is(.foo, .bar, .baz)'
const elementsOfInterest = myRootElement.querySelectorAll(selector);
For more complex cases, it depends. However, I'd say a CSS selector is probably the most efficient way to search for elements: browsers optimize it under the hood so we don't have to. I'm not sure about XPath though.
对于更复杂的情况,这要视情况而定。然而,我想说的是,css选择器可能是搜索元素的最有效方式:浏览器在幕后对其进行了优化,因此我们不必这样做。不过,我对XPath不是很确定。
更多回答
... and then I use it like so myRootElement.querySelectorAll(selector)
?
..。然后我像这样使用它:myRootElement.querySelectorAll(选择器)?
@einpoklum Yes.
@einpoklum是的。
So, I added that to the answer, since it makes it clearer (to me at least).
因此,我把这句话加到了答案中,因为这让它更清楚了(至少对我来说)。
我是一名优秀的程序员,十分优秀!