javascript 如何过滤 QuerySelectorAll 返回的元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6791112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to filter elements returned by QuerySelectorAll
提问by timw4mail
I'm working on a javascript libarary, and I use this function to match elements:
我正在开发一个 javascript 库,我使用这个函数来匹配元素:
$ = function (a)
{
var x;
if (typeof a !== "string" || typeof a === "undefined"){ return a;}
//Pick the quickest method for each kind of selector
if(a.match(/^#([\w\-]+$)/))
{
return document.getElementById(a.split('#')[1]);
}
else if(a.match(/^([\w\-]+)$/))
{
x = document.getElementsByTagName(a);
}
else
{
x = document.querySelectorAll(a);
}
//Return the single object if applicable
return (x.length === 1) ? x[0] : x;
};
There are occasions where I would want to filter the result of this function, like pick out a div span
, or a #id div
or some other fairly simple selector.
有时我想过滤这个函数的结果,比如选择 a div span
,或 a#id div
或其他一些相当简单的选择器。
How can I filter these results? Can I create a document fragement, and use the querySelectorAll method on that fragment, or do I have to resort to manual string manipulation?
如何过滤这些结果?我可以创建一个文档片段,并在该片段上使用 querySelectorAll 方法,还是必须求助于手动字符串操作?
I only care about modern browsers, and IE8+.
我只关心现代浏览器和 IE8+。
If you want to look at the rest of my library, it's here: https://github.com/timw4mail/kis-js
如果你想看看我图书馆的其余部分,它在这里:https: //github.com/timw4mail/kis-js
Edit:
编辑:
To clarify, I want to be able to do something like $_(selector).children(other_selector) and return the children elements matching that selector.
澄清一下,我希望能够执行诸如 $_(selector).children(other_selector) 之类的操作并返回与该选择器匹配的子元素。
Edit:
编辑:
So here's my potential solution to the simplest selectors:
所以这是我对最简单的选择器的潜在解决方案:
tag_reg = /^([\w\-]+)$/;
id_reg = /#([\w\-]+$)/;
class_reg = /\.([\w\-]+)$/;
function _sel_filter(filter, curr_sel)
{
var i,
len = curr_sel.length,
matches = [];
if(typeof filter !== "string")
{
return filter;
}
//Filter by tag
if(filter.match(tag_reg))
{
for(i=0;i<len;i++)
{
if(curr_sell[i].tagName.toLowerCase() == filter.toLowerCase())
{
matches.push(curr_sel[i]);
}
}
}
else if(filter.match(class_reg))
{
for(i=0;i<len;i++)
{
if(curr_sel[i].classList.contains(filter))
{
matches.push(curr_sel[i]);
}
}
}
else if(filter.match(id_reg))
{
return document.getElementById(filter);
}
else
{
console.log(filter+" is not a valid filter");
}
return (matches.length === 1) ? matches[0] : matches;
}
It takes a tag like div
, an id, or a class selector, and returns the matching elements with the curr_sel
argument.
它接受像div
、id 或类选择器这样的标签,并返回带有curr_sel
参数的匹配元素。
I don't want to have to resort to a full selector engine, so is there a better way?
我不想求助于完整的选择器引擎,那么有更好的方法吗?
回答by jAndy
I don't think I get the question right. Why would you want to "filter" the result of querySelectorAll()
which infact, is some kind of a filter itself. If you query for div span
or even better #id div
, those results are already filtered, no ?
我不认为我的问题是正确的。你为什么要“过滤”querySelectorAll()
实际上是某种过滤器本身的结果。如果您查询div span
甚至更好#id div
,这些结果已经被过滤了,不是吗?
However, you can apply Array.prototype.filter
to the static result of querySelectorAll
like follows:
但是,您可以应用Array.prototype.filter
到querySelectorAll
类似如下的静态结果:
var filter = Array.prototype.filter,
result = document.querySelectorAll('div'),
filtered = filter.call( result, function( node ) {
return !!node.querySelectorAll('span').length;
});
That code would first use querySelectorAll()
to query for all <div>
nodes within the document. Afterwards it'll filter for <div>
nodes which contain at least one <span>
. That code doesn't make much sense and is just for demonstrative purposes (just in case some SO member wants to create a donk comment)
该代码将首先用于querySelectorAll()
查询<div>
文档中的所有节点。之后它将过滤<div>
包含至少一个<span>
. 该代码没有多大意义,仅用于演示目的(以防万一某些 SO 成员想要创建一个唐克评论)
update
更新
You can also filter with Element.compareDocumentPosition
. I'll also tell if Elements are disconnected
, following
, preceding
, or contained
. See MDC .compareDocumentPosition()
您还可以使用 过滤Element.compareDocumentPosition
。我还会告诉如果元素disconnected
,following
,preceding
,或contained
。见MDC .compareDocumentPosition()
回答by lasec0203
Note: NodeList is not a genuine array, that is to say it doesn't have the array methods like slice, some, map etc. To convert it into an array, try Array.from(nodeList).
注意:NodeList 不是真正的数组,也就是说它没有slice、some、map 等数组方法。要转换成数组,可以试试Array.from(nodeList)。
ref: https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
参考:https: //developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
for example:
例如:
let highlightedItems = Array.from(userList.querySelectorAll(".highlighted"));
highlightedItems.filter((item) => {
//...
})
回答by Scott Weaver
Most concise way in 2019 is with spread syntax...
plus an array literal [...]
, which work great with iterable objects like the NodeList returned by querySelectorAll
:
2019 年最简洁的方法是使用扩展语法...
加上数组文字[...]
,它适用于可迭代对象,例如由 返回的 NodeList querySelectorAll
:
[...document.querySelectorAll(".myClass")].filter(el=>{/*your code here*/})
[...document.querySelectorAll(".myClass")].filter(el=>{/*your code here*/})
回答by user113716
Some browsers that support qsa
also support a non-standard matchesSelector
method, like:
一些支持的浏览器qsa
也支持非标准matchesSelector
方法,例如:
element.webkitMatchesSelector('.someSelector')
...that will return a boolean representing whether element
matched the selector provided. So you could iterate the collection, and apply that method, retaining positive results.
...这将返回一个布尔值,表示是否element
与提供的选择器匹配。所以你可以迭代集合,并应用该方法,保留积极的结果。
In browsers that don't have a matchesSelector
, you'd probably need to build your own selector based method similar to the selector engine you're building.
在没有 的浏览器中matchesSelector
,您可能需要构建自己的基于选择器的方法,类似于您正在构建的选择器引擎。