Javascript querySelector 搜索直接孩子
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6481612/
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
querySelector search immediate children
提问by disfated
I have some jquery-like function:
我有一些类似 jquery 的功能:
function(elem) {
return $('> someselector', elem);
};
The question is how can i do the same with querySelector()
?
问题是我怎么能做同样的事情querySelector()
?
The problem is >
selector in querySelector()
requires parent to be explicitly specified. Is there any workaround?
问题是>
选择器querySelector()
需要明确指定父级。有什么解决方法吗?
采纳答案by disfated
Complete :scope polyfill
完成 :scope polyfill
As avetiskhas mentionedSelectors API 2 uses :scope
pseudo-selector.
To make this work in all browsers (that support querySelector
) here is the polyfill
正如avetisk所提到的Selectors API 2 使用:scope
伪选择器。
为了在所有浏览器(支持querySelector
)中工作,这里是 polyfill
(function(doc, proto) {
try { // check if browser supports :scope natively
doc.querySelector(':scope body');
} catch (err) { // polyfill native methods if it doesn't
['querySelector', 'querySelectorAll'].forEach(function(method) {
var nativ = proto[method];
proto[method] = function(selectors) {
if (/(^|,)\s*:scope/.test(selectors)) { // only if selectors contains :scope
var id = this.id; // remember current element id
this.id = 'ID_' + Date.now(); // assign new unique id
selectors = selectors.replace(/((^|,)\s*):scope/g, '#' + this.id); // replace :scope with #ID
var result = doc[method](selectors);
this.id = id; // restore previous id
return result;
} else {
return nativ.call(this, selectors); // use native code for other selectors
}
}
});
}
})(window.document, Element.prototype);
Usage
用法
node.querySelector(':scope > someselector');
node.querySelectorAll(':scope > someselector');
For historical reasons, my previous solution
由于历史原因,我之前的解决方案
Based on all answers
基于所有答案
// Caution! Prototype extending
Node.prototype.find = function(selector) {
if (/(^\s*|,\s*)>/.test(selector)) {
if (!this.id) {
this.id = 'ID_' + new Date().getTime();
var removeId = true;
}
selector = selector.replace(/(^\s*|,\s*)>/g, '#' + this.id + ' >');
var result = document.querySelectorAll(selector);
if (removeId) {
this.id = null;
}
return result;
} else {
return this.querySelectorAll(selector);
}
};
Usage
用法
elem.find('> a');
回答by avetisk
Though it's not a full answer, you should keep an eye on the W3C Selector API v.2which is already available in Google Chrome and Safari 7.x (both desktop and mobile), but as far as I have tested, still not there in Firefox and IE.
虽然这不是一个完整的答案,但您应该关注W3C Selector API v.2,它已经在 Google Chrome 和 Safari 7.x(桌面和移动)中可用,但据我测试,仍然没有在 Firefox 和 IE 中。
function(elem) {
return elem.querySelectorAll(':scope > someselector');
};
回答by user113716
You can't. There's no selector that will simulate your starting point.
你不能。没有选择器可以模拟您的起点。
The way jQuery does it (more because of a way that qsa
behaves that is not to their liking), is that they check to see if elem
has an ID, and if not, they temporarily add an ID, then create a full selector string.
jQuery 这样做的方式(更多是因为qsa
他们不喜欢的行为方式)是他们检查是否elem
有 ID,如果没有,他们临时添加一个 ID,然后创建一个完整的选择器字符串。
Basically you'd do:
基本上你会这样做:
var sel = '> someselector';
var hadId = true;
if( !elem.id ) {
hadID = false;
elem.id = 'some_unique_value';
}
sel = '#' + elem.id + sel;
var result = document.querySelectorAll( sel );
if( !hadId ) {
elem.id = '';
}
This certainly isn't jQuery code, but from what I remember, it is basically what they do. Not just in this situation, but in any situation where you're running a selector from the context of a nested element.
这当然不是 jQuery 代码,但据我所知,这基本上就是他们所做的。不仅在这种情况下,而且在您从嵌套元素的上下文中运行选择器的任何情况下。
回答by Vlad GURDIGA
If you know the tag name of the element that you're looking into, then you can use it in the selector to achieve what you want.
如果您知道要查看的元素的标签名称,那么您可以在选择器中使用它来实现您想要的。
For example if you have a <select>
that has <option>
s and <optgroups>
, and you only want the <option>
s that are its immediate children, not the ones inside <optgoups>
:
例如,如果你有一个<select>
有<option>
S和<optgroups>
,你只希望<option>
这是其直接的孩子,而不是里面的那些小号<optgoups>
:
<select>
<option>iPhone</option>
<optgroup>
<option>Nokia</option>
<option>Blackberry</option>
</optgroup>
</select>
So, having a reference to the select element, you can — surprisingly — get its immediate children like this:
所以,有了对 select 元素的引用,你可以——令人惊讶地——像这样获得它的直接子元素:
selectElement.querySelectorAll('select > option')
It seems to work in Chrome, Safari, and Firefox, but didn't test in IEs. =/
它似乎适用于 Chrome、Safari 和 Firefox,但未在 IE 中进行测试。=/
回答by tuomassalo
If you want to eventually find direct children (and not e.g. > div > span
), you can try Element.matches():
如果你想最终找到直接的孩子(而不是 eg > div > span
),你可以尝试Element.matches():
const elems = Array.from(elem.children).filter(e => e.matches('.my-class'))
回答by Liangliang Zheng
CLAIM
宣称
Personally I would take the answer from patrick dw, and +1 his answer, my answer is for seeking alternative solution. I don't think it deserves a downvote.
我个人会从 patrick dw 那里得到答案,并+1 他的答案,我的答案是寻求替代解决方案。我认为它不值得投反对票。
Here is my attempt :
这是我的尝试:
function q(elem){
var nodes = elem.querySelectorAll('someSeletor');
console.log(nodes);
for(var i = 0; i < nodes.length; i++){
if(nodes[i].parentNode === elem) return nodes[i];
}
}
回答by Davi
That worked for me:
这对我有用:
Node.prototype.search = function(selector)
{
if (selector.indexOf('@this') != -1)
{
if (!this.id)
this.id = "ID" + new Date().getTime();
while (selector.indexOf('@this') != -1)
selector = selector.replace('@this', '#' + this.id);
return document.querySelectorAll(selector);
} else
return this.querySelectorAll(selector);
};
you will have to pass the @this keywork before the > when you want to search for immediate children.
当您要搜索直系子项时,您必须在 > 之前传递 @this 关键字。
回答by csuwldcat
The following is a simplified, generic method for running any CSS selector query over only direct children - it also accounts for combined queries, like "foo[bar], baz.boo"
:
以下是一种简化的通用方法,用于仅在直接子项上运行任何 CSS 选择器查询 - 它还考虑了组合查询,例如"foo[bar], baz.boo"
:
var count = 0;
function queryChildren(element, selector) {
var id = element.id,
guid = element.id = id || 'query_children_' + count++,
attr = '#' + guid + ' > ',
selector = attr + (selector + '').replace(',', ',' + attr, 'g');
var result = element.parentNode.querySelectorAll(selector);
if (!id) element.removeAttribute('id');
return result;
}
*** Example Use ***
queryChildren(someElement, '.foo, .bar[xyz="123"]');
回答by dy_
There's a query-relativelib, which is quite handy replacement for query-selector. It polyfills children selector '> *'
and :scope
(inc. IE8), as well as normalizes :root
selector.
Also it provides some special relative pseudos like :closest
, :parent
, :prev
, :next
, just in case.
有一个查询相关的库,它是query-selector 的非常方便的替代品。它填充子选择器'> *'
和:scope
(包括 IE8),以及规范化:root
选择器。它还提供了一些特殊的相对伪代码,例如:closest
, :parent
, :prev
, :next
,以防万一。
回答by Zeeshan Anjum
check if element have id else add random id and do search based on it
检查元素是否有 id 否则添加随机 id 并根据它进行搜索
function(elem) {
if(!elem.id)
elem.id = Math.random().toString(36).substr(2, 10);
return elem.querySelectorAll(elem.id + ' > someselector');
};
will do same thing as
会做同样的事情
$("> someselector",$(elem))