web-dev-qa-db-ja.com

querySelectorは直接の子を検索します

Jqueryのような関数がいくつかあります。

_function(elem) {
    return $('> someselector', elem);
};
_

問題は、どのようにquerySelector()で同じことができますか?

問題は、querySelector()の_>_セレクターが、明示的に指定された親を必要とすることです。回避策はありますか?

81
disfated

完全:スコープポリフィル

avetisk has 言及 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');
18
disfated

完全な答えではありませんが、Googleですでに利用可能な W3C Selector API v.2 に注意する必要がありますChromeおよびSafari 7.x(両方デスクトップとモバイル)、しかし私がテストした限りでは、FirefoxとIEにはまだありません。

function(elem) {
  return elem.querySelectorAll(':scope > someselector');
};
103
avetisk

できません。出発点をシミュレートするセレクタはありません。

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のコードではありませんが、私が覚えていることから、それは基本的に彼らがすることです。この状況だけでなく、ネストされた要素のコンテキストからセレクターを実行している状況でも。

Sizzleのソースコード

31
user113716

探している要素のタグ名がわかっている場合は、セレクタでそれを使用して、目的を達成できます。

たとえば、<select><option>を持つ<optgroups>があり、<option>内ではなく、直接の子である<optgoups>sのみが必要な場合:

<select>
  <option>iPhone</option>
  <optgroup>
    <option>Nokia</option>
    <option>Blackberry</option>
  </optgroup>
</select>

したがって、select要素への参照があれば、驚くべきことに、次のように直接の子を取得できます。

selectElement.querySelectorAll('select > option')

Chrome、Safari、Firefoxで動作するようですが、IEではテストしていません。 = /

4
Vlad GURDIGA

最終的に直接の子を見つけたい場合(例:> div > span)、 Element.matches() を試すことができます。

const elems = Array.from(elem.children).filter(e => e.matches('.my-class'))
2
tuomassalo

それは私のために働いた:

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キーワードを渡す必要があります。

1
Davi

以下は、直接の子のみで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"]');
1
csuwldcat

query-relative libがあり、これはquery-selectorの非常に便利な代替品です。子セレクター'> *'および:scope(IE8を含む)をポリフィルし、:rootセレクターを正規化します。また、念のため、:closest:parent:prev:nextなどの特別な相対疑似も提供します。

1
dy_

[〜#〜] claim [〜#〜]

個人的に私は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];
    }
}

http://jsfiddle.net/Lgaw5/8/ を参照してください

1

要素にIDがあるかどうかを確認し、そうでない場合はランダムIDを追加し、それに基づいて検索を実行します

function(elem) {
      if(!elem.id)
          elem.id = Math.random().toString(36).substr(2, 10);
      return elem.querySelectorAll(elem.id + ' > someselector');
    };

と同じことをします

$("> someselector",$(elem))
0
Zeeshan Anjum