Mam funkcję podobną do jQuery:
function(elem) {
return $('> someselector', elem);
};
Pytanie brzmi, jak mogę zrobić to samo z querySelector()
?
Problem polega na tym, że >
selektor querySelector()
wymaga jawnego określenia elementu nadrzędnego. Czy jest jakieś obejście?
javascript
css-selectors
selectors-api
disfated
źródło
źródło
Odpowiedzi:
Chociaż nie jest to pełna odpowiedź, powinieneś mieć oko na W3C Selector API v.2, który jest już dostępny w większości przeglądarek, zarówno stacjonarnych, jak i mobilnych, z wyjątkiem IE (Edge wydaje się obsługiwać): zobacz pełną listę wsparcia .
function(elem) { return elem.querySelectorAll(':scope > someselector'); };
źródło
:scope
jest nadal określony na drafts.csswg.org/selectors-4/#the-scope-pseudo . Jak dotąd tylko<style scoped>
atrybut został usunięty; nie jest jasne, czy doprowadzi to również do:scope
usunięcia (ponieważ<style scoped>
był to ważny przypadek użycia:scope
).Nie możesz. Nie ma selektora, który symulowałby Twój punkt początkowy.
Sposób, w jaki jQuery to robi (bardziej ze względu na sposób,
qsa
który nie odpowiada ich preferencjom) polega na tym, że sprawdzają, czyelem
ma identyfikator, a jeśli nie, tymczasowo dodają identyfikator, a następnie tworzą pełny ciąg selektora.Zasadniczo zrobiłbyś:
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 = ''; }
Z pewnością nie jest to kod jQuery, ale z tego, co pamiętam, to w zasadzie to, co robią. Nie tylko w tej sytuacji, ale w każdej sytuacji, w której uruchamiasz selektor z kontekstu zagnieżdżonego elementu.
Kod źródłowy dla Sizzle
źródło
Kompletne: wypełnienie lunety
Jak wspomniał avetisk , API 2 Selectors używa pseudo-selektora. Aby to działało we wszystkich przeglądarkach (które obsługują ), oto polyfill
: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);
Stosowanie
node.querySelector(':scope > someselector'); node.querySelectorAll(':scope > someselector');
Ze względów historycznych moje poprzednie rozwiązanie
Na podstawie wszystkich odpowiedzi
// 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); } };
Stosowanie
elem.find('> a');
źródło
Date.now()
nie jest obsługiwany przez starsze przeglądarki i może zostać zastąpiony przeznew Date().getTime()
Jeśli chcesz w końcu znaleźć bezpośrednie dzieci (a nie np.
> div > span
), Możesz spróbować 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>
źródło
Jeśli znasz nazwę tagu elementu, którego szukasz, możesz użyć jej w selektorze, aby osiągnąć to, co chcesz.
Na przykład, jeśli masz a,
<select>
które ma<option>
s i<optgroups>
i chcesz tylko<option>
s, które są jego bezpośrednimi dziećmi, a nie tymi w środku<optgoups>
:<select> <option>iPhone</option> <optgroup> <option>Nokia</option> <option>Blackberry</option> </optgroup> </select>
Tak więc, mając odniesienie do elementu select, możesz - co zaskakujące - pobrać jego bezpośrednie elementy potomne w następujący sposób:
selectElement.querySelectorAll('select > option')
Wygląda na to, że działa w Chrome, Safari i Firefox, ale nie testował w IE. = /
źródło
<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');
-> Wszystkie 4 elementy li zostaną wybrane!<select>
w tym samym rodzicu były dwa elementy.ROSZCZENIE
Osobiście wziąłbym odpowiedź od patryka dw i +1 jego odpowiedzi, moja odpowiedź jest taka, aby szukać alternatywnego rozwiązania. Myślę, że nie zasługuje na złą opinię.
Oto moja próba:
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]; } }
zobacz http://jsfiddle.net/Lgaw5/8/
źródło
querySelector
, co oznacza, że:eq()
nie można go użyć. Nawet gdyby tak było, twój selektor zwróciłby element, który ma:eq()
się pojawić na stronie, a nie:eq()
do indeksu jego elementu nadrzędnego (czyli tam, gdzie go otrzymujeszidx
).elem
jest pod indeksem 4, ale jest poprzedni element siostrzany, który ma innytagName
, ale zagnieżdżony w nim element z dopasowaniemtagName
, ten zagnieżdżony element zostanie uwzględniony w wynikach przed tym, na który celujesz, ponownie odrzucając indeks. Oto przykład$('> someselector', elem);
; o)Poniżej przedstawiono uproszczoną, ogólną metodę uruchamiania dowolnego zapytania selektora CSS tylko dla bezpośrednich elementów potomnych - uwzględnia również zapytania łączone, takie jak
"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"]');
źródło
Istnieje biblioteka zależna od zapytania , która jest całkiem przydatnym zamiennikiem dla selektora zapytania . Wypełnia selektor dzieci
'> *'
i:scope
(w tym IE8), a także normalizuje:root
selektor. Również zapewnia pewne szczególne względne pseudos jak:closest
,:parent
,:prev
,:next
, na wszelki wypadek.źródło
To zadziałało dla mnie:
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); };
będziesz musiał przekazać @this keywork przed>, jeśli chcesz szukać najbliższych dzieci.
źródło
sprawdź, czy element ma id, w przeciwnym razie dodaj losowy identyfikator i wykonaj wyszukiwanie na jego podstawie
function(elem) { if(!elem.id) elem.id = Math.random().toString(36).substr(2, 10); return elem.querySelectorAll(elem.id + ' > someselector'); };
zrobi to samo, co
$("> someselector",$(elem))
źródło