Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 查询选择器搜索直接子项_Javascript_Css Selectors_Selectors Api - Fatal编程技术网

Javascript 查询选择器搜索直接子项

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

我有一些类似jquery的函数:

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')