我有一个类似于jQuery的函数:
function(elem) {
return $('> someselector', elem);
};
问题是如何使用querySelector()
实现同样的效果?
querySelector()
中的>
选择器需要显式指定父级。是否有任何解决方法?
我有一个类似于jQuery的函数:
function(elem) {
return $('> someselector', elem);
};
问题是如何使用querySelector()
实现同样的效果?
querySelector()
中的>
选择器需要显式指定父级。是否有任何解决方法?
虽然这不是完整的答案,但你应该关注W3C选择器API v.2,它已经在大多数桌面和移动浏览器中提供,除了IE(Edge似乎支持):查看完整的支持列表。
function(elem) {
return elem.querySelectorAll(':scope > someselector');
};
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代码,但据我所记,它基本上就是他们所做的事情。不仅在这种情况下,而且在任何情况下,当您从嵌套元素的上下文中运行选择器时。
正如avetisk所提到的那样,Selectors API 2使用:scope
伪选择器。
为了使这在所有支持querySelector
的浏览器中工作,这里提供了填充。
(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');
Date.now()
不被旧版浏览器支持,可以用 new Date().getTime()
替代。 - Christophe如果你想最终找到直接子元素(而不是例如> div > span
),你可以尝试使用Element.matches():
const elem = document.body
const elems = [...elem.children].filter(e => e.matches('b'))
console.log(elems)
<a>1</a>
<b>2</b>
<b>3</b>
<b>4</b>
<s>5</s>
声明
个人认为,我会采纳Patrick 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];
}
}
querySelector
结合使用,这意味着无法使用 :eq()
。即使可以,您的选择器也将返回 :eq()
到其在页面上的外观的元素,而不是其父级的索引(这就是您获取idx
的地方)。 - user113716elem
在索引4处,但有一个先前的兄弟节点具有不同的tagName
,但它内部嵌套了一个具有匹配的tagName
的元素,则该嵌套元素将在您要定位的元素之前包含在结果中,再次扰乱索引。这里有一个例子。 - user113716<option>
和<optgroup>
的<select>
,并且您只想获取其直接子级的<option>
,而不是<optgroup>
中的子级:<select>
<option>iPhone</option>
<optgroup>
<option>Nokia</option>
<option>Blackberry</option>
</optgroup>
</select>
所以,如果您有选择元素的引用,您可以通过以下方式-令人惊讶地-获取它的直接子元素:
selectElement.querySelectorAll('select > option')
它似乎在Chrome、Safari和Firefox中运行良好,但没有在IE中进行测试。 =/
<select>
元素,那就糟糕了。 - Tomáš Zato"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"]');
有一个名为query-relative的库,它是查询选择器(query-selector)的方便替代品。它在子元素选择器'> *'
和:scope
(包括IE8)上提供了polyfill,同时规范化了:root
选择器。
此外,它还提供了一些特殊的相对伪类,例如:closest
、:parent
、:prev
、:next
,以备不时之需。
这个对我有用:
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);
};
当您想搜索直接子元素时,必须在“>”之前通过@this关键字。
检查元素是否有ID,否则添加随机ID并基于此进行搜索
function(elem) {
if(!elem.id)
elem.id = Math.random().toString(36).substr(2, 10);
return elem.querySelectorAll(elem.id + ' > someselector');
};
将会执行与之前相同的操作
$("> someselector",$(elem))
:scope
仍然在 https://drafts.csswg.org/selectors-4/#the-scope-pseudo 中有定义。目前只是<style scoped>
属性被移除了;不清楚这是否也会导致:scope
被移除(因为<style scoped>
是:scope
的一个重要用例)。 - John Mellor