querySelector ricerca immediata bambini

Ho qualche jquery-come funzione:

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

La domanda è: come posso fare lo stesso con querySelector()?

Il problema è > selettore in querySelector() genitore richiede di essere specificato in modo esplicito. C’è qualche soluzione alternativa?

Ho aggiunto una risposta che può funzionare meglio per voi, fatemi sapere 😉

OriginaleL’autore disfated | 2011-06-26

10 risposte

  1. 84

    Anche se non è una risposta completa, si dovrebbe tenere un occhio sul Selettore di W3C API v. 2 che è già disponibile in Google Chrome e Safari 7.x (sia desktop che mobile), ma, per quanto ho provato, ancora non c’è in Firefox e IE.

    function(elem) {
      return elem.querySelectorAll(':scope > someselector');
    };
    Questa è la risposta corretta. Tuttavia, browser il supporto è limitato e avrete bisogno di un spessore se si desidera utilizzarlo. Ho costruito scopedQuerySelectorShim per questo scopo.
    L’ :attributo scope è stato rimosso dalla specifica corrente.
    In realtà, :scope è ancora specificato in drafts.csswg.org/selectors-4/#the-scope-pseudo. Finora è solo la <style scoped> attributo che ha ottenuto rimosso; non è chiaro se questo porterà anche a :scope di essere rimosso (dal <style scoped> è stato un importante caso di utilizzo per :scope).

    OriginaleL’autore avetisk

  2. 29

    Non si può. Non c’è nessun selettore che consente di simulare il punto di partenza.

    Il modo jQuery (più a causa di un modo che qsa si comporta in modo che non è di loro gradimento), è che essi controllare per vedere se elem ha un ID, e se non, temporaneamente aggiungere un ID, quindi la creazione di un selettore di stringa.

    Fondamentalmente devi fare:

    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 = '';
    }

    Questo non è certamente codice jQuery, ma da quello che mi ricordo, è fondamentalmente quello che fanno. Non solo in questa situazione, ma in qualsiasi situazione in cui si sta eseguendo un selettore dal contesto di un elemento nidificato.

    Il codice sorgente per Friggere

    Corrette al momento della scrittura, ma vedere @avetisk risposta per un metodo aggiornato.

    OriginaleL’autore user113716

  3. 16

    Completo :ambito polyfill

    Come avetisk ha menzionato Selettori API 2 utilizza :scope pseudo-selettore.

    Per fare questo lavoro in tutti i browser (che supportano querySelector) qui è il 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);

    Utilizzo

    node.querySelector(':scope > someselector');
    node.querySelectorAll(':scope > someselector');

    Per ragioni storiche, la mia soluzione precedente

    Basato su tutte le risposte

    //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);
        }
    };

    Utilizzo

    elem.find('> a');
    Date.now() non è supportata dal browser meno recenti, e potrebbe essere sostituito con new Date().getTime()
    che su di <style scoped>non :scope. Sono cose completamente diverse.

    OriginaleL’autore

  4. 5

    Se si conosce il nome del tag dell’elemento che stai cercando, allora è possibile utilizzare il selettore per ottenere quello che vuoi.

    Per esempio, se si dispone di un <select> che ha <option>s e <optgroups>e si desidera solo la <option>s che sono i suoi figli immediati, non quelle all’interno <optgoups>:

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

    Così, avendo un riferimento all’elemento di selezione, è possibile — a sorpresa — ottenere la sua immediata bambini come questo:

    selectElement.querySelectorAll('select > option')

    Sembra funzionare in Chrome, Safari e Firefox, ma non prova in Placca. =/

    Attenzione: Questa non è una risposta in realtà limitare la portata. Se il motivo è ripetuto più profondo nido il livello è ancora saranno selezionati anche se non è diretto ai bambini. <ul id="start"> <li>A</li> <li> <ul> <li>b</li> <li>c</li> </ul> </li> </ul> var result = document.getElementById('start').querySelectorAll('ul>li'); -> Tutti i 4 elementi li saranno selezionati!

    OriginaleL’autore Vlad GURDIGA

  5. 1

    PRETENDIAMO

    Personalmente vorrei prendere la risposta da patrick dw, e +1 la sua risposta, la mia risposta è per la ricerca di soluzioni alternative. Non penso che si merita un downvote.

    Qui è il mio tentativo :

    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];
        }
    }

    vedere http://jsfiddle.net/Lgaw5/8/

    Paio di problemi. @disfated vuole per lavorare con querySelectoril che significa che :eq() non può essere utilizzato. Anche se possibile, il selettore dovrebbe restituire l’elemento che è :eq() per il suo aspetto sulla pagina, non :eq() l’indice di suo padre (che è dove stai ricevendo il idx).
    +1 su :eq() & querySelector. E devo aggiungere il contesto $(elem).parent().
    Purtroppo non funziona. Quando il selettore viene eseguito dal contesto del padre, inizia con la parte sinistra del bambino e rileva tutti gli elementi corrispondenti, non importa quanto profondamente annidato, continua. Così dicono i elem è indice 4, ma c’è un precedente di pari livello che ha un diverso tagNamema ha nidificato all’interno di un elemento con il corrispondente tagNametale elemento nidificato saranno incluse nei risultati prima di un target, di nuovo gettato l’indice. Ecco un esempio
    …in ogni caso, quello che si sta ultimamente facendo è una versione più articolata del codice in questione, che funziona. $('> someselector', elem); ;o)
    Nota che ho idx++, tenta jsfiddle.net/Lgaw5/2

    OriginaleL’autore Liangliang Zheng

  6. 1

    Che ha funzionato per me:

    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);
    };

    si dovrà passare il @questa tastiera prima dell’ > quando si desidera effettuare la ricerca per immediato bambini.

    Sembra lo stesso come l’currenty accettata risposta… a Proposito, qual è il punto di strano “@” sintassi? Perché non solo il test per “>” con regexp?

    OriginaleL’autore Davi

  7. 1

    La seguente è una versione semplificata, metodo generico per l’esecuzione di qualsiasi selettore CSS query più solo i bambini, ma anche di conti per le query combinate, come "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"]');

    OriginaleL’autore csuwldcat

  8. 1

    C’è un query relativa lib, che è molto pratico di ricambio per query di selezione. Si polyfills bambini selettore '> *' e :scope (inc. IE8), così come normalizza :root di selezione.
    Inoltre, esso fornisce alcuni particolari relativi fittizio come :closest, :parent, :prev, :next, nel caso in cui.

    OriginaleL’autore Dmitry_F

  9. 0

    controllare se l’elemento hanno id altro aggiungere casuale id e fare una ricerca basata su di esso

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

    farà la stessa cosa come

    $("> someselector",$(elem))

    OriginaleL’autore Zeeshan Anjum

  10. 0

    Se si vuole, alla fine, trovano diretta i bambini (e non ad esempio > div > span), si può provare Elemento.matches():

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

    OriginaleL’autore tuomassalo

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *