Javascript 查询选择器搜索直接子项
我有一些类似jquery的函数:Javascript 查询选择器搜索直接子项,javascript,css-selectors,selectors-api,Javascript,Css Selectors,Selectors Api,我有一些类似jquery的函数: function(elem) { return $('> someselector', elem); }; 问题是如何使用querySelector() 问题是querySelector()中的选择器要求显式指定父级。有什么解决办法吗?你不能。没有选择器可以模拟您的起点 jQuery这样做的方式(更多是因为qsa的行为方式不符合他们的喜好),就是检查elem是否有ID,如果没有,他们会临时添加ID,然后创建一个完整的选择器字符串 基本上你会: v
function(elem) {
return $('> someselector', elem);
};
问题是如何使用querySelector()
问题是
querySelector()
中的
选择器要求显式指定父级。有什么解决办法吗?你不能。没有选择器可以模拟您的起点
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代码,但根据我的记忆,它基本上就是它们所做的。不仅在这种情况下,而且在从嵌套元素的上下文运行选择器的任何情况下
索赔
就我个人而言,我会从patrick dw那里得到答案,+1他的答案,我的答案是寻求替代解决方案。我认为它不值得投否决票
以下是我的尝试:
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];
}
}
函数q(elem){
var nodes=elem.querySelectorAll('someSeletor');
console.log(节点);
对于(var i=0;i
请参见为我工作的:
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 keywork,然后再通过>。以下是一种简化的通用方法,用于仅对直接子代运行任何CSS选择器查询-它还考虑组合查询,如
“foo[bar],baz.boo”
:
完成:范围polyfill
与选择器一样,API 2使用了:范围伪选择器。
要在所有浏览器(支持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);
用法
出于历史原因,我以前的解决方案
根据所有答案
// 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');
虽然这并不是一个完整的答案,但你应该关注的是,除了IE(Edge似乎支持)之外,大多数浏览器(台式机和移动设备)都已经提供了这样的功能
有一个lib,它非常方便地替代了查询选择器。它多填充子选择器'>*'
和:scope
(包括IE8),并规范化:root
选择器。
此外,它还提供了一些特殊的相对伪码,如:nest
,:parent
,:prev
,:next
,以防万一。检查元素是否有id,或者添加随机id并基于它进行搜索
function(elem) {
if(!elem.id)
elem.id = Math.random().toString(36).substr(2, 10);
return elem.querySelectorAll(elem.id + ' > someselector');
};
我会做和你一样的事
$("> someselector",$(elem))
如果知道要查找的元素的标记名,那么可以在选择器中使用它来实现所需的功能
例如,如果您的
具有
和
,并且您只希望
是其直接子项,而不是
中的子项:
它似乎可以在Chrome、Safari和Firefox中使用,但没有在IEs中测试=/ 如果您希望最终找到直接子项(而不是例如>div>span
),您可以尝试:
const elem=document.body
常量elems=[…elem.children].filter(e=>e.matches('b'))
console.log(元素)
1
2.
3.
4.
5
这有几个问题@disfated希望它与查询选择器
一起工作,这意味着:eq()
不能使用。即使可以,选择器也会将:eq()
元素返回到页面上的外观,而不是将:eq()
返回到其父元素的索引(这是您获得idx
)的地方。+1关于:eq()和querySelector。我应该添加上下文$(elem).parent()。不幸的是,这也不起作用。当选择器从父元素的上下文运行时,它从最左边的子元素开始,并查找所有匹配的元素,无论嵌套有多深,继续。假设元素位于索引4,但有一个以前的同级标记名有不同的标记名
,但它在其中嵌套了一个元素,该元素与匹配的标记名
,该嵌套元素将在目标元素之前包含在结果中,再次抛出索引。。。不管怎样,您最终要做的是问题中代码的更复杂版本,这确实有效<代码>$('>someselector',elem)代码>;o) 是的,但是你需要硬编码这个增量。这需要事先了解它。如果我再加一个类似的元素,它就会再次被破坏;o) 我添加了一个可能更适合您的答案,请告诉我;)似乎与当前接受的相同。。。顺便问一下,奇怪的“@this”语法有什么意义?为什么不用regexp测试“>”?Date.now()
不受旧浏览器支持,可以用new Date()替换。getTime()
这是正确的答案。然而,如果你想使用它,你需要一个垫片。我是为此目的而构建的:scope属性。实际上,:scope
仍在指定。到目前为止,只有
属性被删除;现在还不清楚这是否会导致:scope
被删除(因为
是:scope
的一个重要用例)。令人惊讶的是:只有Edge不支持这一点:)到2021年,所有现代浏览器都支持这一点。在撰写本文时正确,但请参阅@avetisk的答案以了解更新的方法。警告:此答案实际上并没有限制范围。若模式在更深的嵌套层重复,即使它不是直接子级,它仍然会被选中<代码>- A
- b
- c
li')代码>->将选择所有4个li元素!上帝禁止在同一个父级中有两个
元素。
function(elem) {
return elem.querySelectorAll(':scope > someselector');
};
function(elem) {
if(!elem.id)
elem.id = Math.random().toString(36).substr(2, 10);
return elem.querySelectorAll(elem.id + ' > someselector');
};
$("> someselector",$(elem))
<select>
<option>iPhone</option>
<optgroup>
<option>Nokia</option>
<option>Blackberry</option>
</optgroup>
</select>
selectElement.querySelectorAll('select > option')