我有一些类似jquery的功能:
function(elem) {
return $('> someselector', elem);
};
问题是我如何对querySelector()
做同样的事情?
问题是>
中querySelector()
选择器要求明确指定父级。有没有解决方法?
答案 0 :(得分:99)
虽然这不是一个完整的答案,但您应该关注Google Chrome和Safari 7.x(桌面版和移动版)中已有的W3C Selector API v.2,但据我测试,仍然在Firefox和IE中没有。
function(elem) {
return elem.querySelectorAll(':scope > someselector');
};
答案 1 :(得分:31)
你做不到。没有选择器会模拟你的起点。
jQuery的做法(更多是因为qsa
表现的方式不符合他们的喜好)是他们检查elem
是否有ID,如果没有,他们会暂时添加一个ID,然后创建一个完整的选择器字符串。
基本上你做的是:
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 = '';
}
这当然不是jQuery代码,但从我记忆中来看,它基本上就是他们所做的。不只是在这种情况下,而是在你从嵌套元素的上下文中运行选择器的任何情况下。
答案 2 :(得分:18)
由于avetisk有mentioned选择器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, '$1#' + 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);
node.querySelector(':scope > someselector');
node.querySelectorAll(':scope > someselector');
由于历史原因,我之前的解决方案
基于所有答案
// 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, '$1#' + this.id + ' >');
var result = document.querySelectorAll(selector);
if (removeId) {
this.id = null;
}
return result;
} else {
return this.querySelectorAll(selector);
}
};
<强>用法强>
elem.find('> a');
答案 3 :(得分:4)
如果你知道你正在研究的元素的标签名称,那么你可以在选择器中使用它来实现你想要的。
例如,如果您的<select>
有<option>
和<optgroups>
,并且您只希望<option>
是其直接子项,而不是里面的那些<optgoups>
:
<select>
<option>iPhone</option>
<optgroup>
<option>Nokia</option>
<option>Blackberry</option>
</optgroup>
</select>
所以,有了对select元素的引用,你可以 - 令人惊讶地 - 得到这样的直接孩子:
selectElement.querySelectorAll('select > option')
它似乎适用于Chrome,Safari和Firefox,但未在IE中进行测试。 = /
答案 4 :(得分:1)
<强> CLAIM 强>
就我个人而言,我会从帕特里克dw那里得到答案,并给出他的回答,我的答案是寻求替代解决方案。我认为它不值得投票。
这是我的尝试:
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];
}
}
答案 5 :(得分:1)
这对我有用:
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);
};
你必须在&gt;之前传递@this键盘。当你想要寻找直接的孩子时。
答案 6 :(得分:1)
以下是仅针对直接子项运行任何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"]');
答案 7 :(得分:1)
有一个query-relative lib,它非常方便替代 query-selector 。它会填充子选择器'> *'
和:scope
(包括IE8),以及标准化:root
选择器。
此外,它提供了一些特殊的相对伪,如:closest
,:parent
,:prev
,:next
,以防万一。
答案 8 :(得分:1)
如果您想最终找到直子(而不是> div > span
),可以尝试Element.matches():
const elems = Array.from(elem.children).filter(e => e.matches('.my-class'))
答案 9 :(得分:0)
检查元素是否有id否则添加随机id并根据它进行搜索
function(elem) {
if(!elem.id)
elem.id = Math.random().toString(36).substr(2, 10);
return elem.querySelectorAll(elem.id + ' > someselector');
};
会做与
相同的事情$("> someselector",$(elem))