Parametr :scope
jest zdefiniowany w selektorach arkusza CSS 4 jako:
Pseudoklasa reprezentująca dowolny element w zestawie kontekstowych elementów referencyjnych. Jest to (potencjalnie pusty) zbiór elementów, np. określony przez
querySelector()
, lub element nadrzędny elementu<style scoped>
, który służy do „określania zakresu” selektora tak, aby pasować tylko do drzewa podrzędnego.
Oto przykład użycia tej funkcji w <style scoped>
(więcej informacji):
<style>
li {
color: blue;
}
</style>
<ul>
<style scoped>
li {
color: red;
}
:scope {
border: 1px solid red;
}
</style>
<li>abc</li>
<li>def</li>
<li>efg</li>
</ul>
<ul>
<li>hij</li>
<li>klm</li>
<li>nop</li>
</ul>
Powoduje to kolorowanie elementów li
pierwszego zakresu (ul
) na czerwono, a dzięki regule :scope
umieszcza obramowanie wokół elementu ul
. W kontekście tego elementu (<style scoped>
) element ul
pasuje do: :scope
. To kontekst lokalny. Gdybyśmy dodali regułę :scope
w zewnętrznym <style>
, pasowałaby ona do całego dokumentu. Zasadniczo jest to odpowiednik :root
.
Elementy kontekstowe
Prawdopodobnie znasz wersje Element
systemu querySelector()
i querySelectorAll()
. Zamiast wysyłać zapytanie dotyczące całego dokumentu, możesz ograniczyć zbiór wyników do elementu kontekstowego:
<ul>
<li id="scope"><a>abc</a></li>
<li>def</li>
<li><a>efg</a></li>
</ul>
<script>
document.querySelectorAll('ul a').length; // 2
var scope = document.querySelector('#scope');
scope.querySelectorAll('a').length; // 1
</script>
Gdy zostaną one wywołane, przeglądarka zwraca typ NodeList
z filtrem, który uwzględnia tylko zbiór węzłów, które a.) pasują do selektora oraz b., które są również potomnymi elementu kontekstu. W drugim przykładzie przeglądarka znajduje wszystkie elementy a
, a potem odfiltrowuje te, których nie ma w elemencie scope
. To działa, ale jeśli nie zachowasz ostrożności, może to prowadzić do dziwnych zachowań. Czytaj dalej.
Gdy selektor querySelector działa nieprawidłowo
W specyfikacji selektora jest naprawdę ważna kwestia, którą użytkownicy często przeoczają. Nawet po wywołaniu funkcji querySelector[All]()
w elemencie selektory nadal dokonują oceny w kontekście całego dokumentu. Oznacza to, że mogą wystąpić nieprzewidziane sytuacje:
scope.querySelectorAll('ul a').length); // 1
scope.querySelectorAll('body ul a').length); // 1
Super! W pierwszym przykładzie ul
jest moim elementem, ale nadal mogę go używać i dopasowywać węzły. W drugim przypadku body
nie jest nawet elementem potomnym mojego elementu, ale „body ul a
” mimo to pasuje. Obie te kwestie są mylące i niezgodne z oczekiwaniami.
Warto tu dokonać porównania z biblioteką jQuery, która działa we właściwym podejściu i działa zgodnie z oczekiwaniami:
$(scope).find('ul a').length // 0
$(scope).find('body ul a').length // 0
...wpisz :scope
, aby rozwiązać te semantyczne łamigłówki.
Naprawianie metody querySelector za pomocą zakresu :scope
Obsługa WebKit niedawno umożliwia korzystanie z pseudoklasy :scope
w: querySelector[All]()
. Możesz ją przetestować w Chrome Canary 27.
Pozwala on ograniczyć selektory do elementu kontekstu. Spójrzmy na przykład. W poniższym przykładzie parametr :scope
służy do określania zakresu selektora na poddrzewo elementu zakresu. Tak, powiedziałem zakres 3 razy!
scope.querySelectorAll(':scope ul a').length); // 0
scope.querySelectorAll(':scope body ul a').length); // 0
scope.querySelectorAll(':scope a').length); // 1
Używanie :scope
sprawia, że semantyka metod querySelector()
staje się bardziej przewidywalna i jest zgodna z działaniami innych osób, takich jak jQuery.
Wydajność jest lepsza?
Jeszcze nie :(
Ciekawi mnie, czy użycie narzędzia :scope
w raporcie QS/QSA może zwiększyć wydajność. Więc... jako dobry inżynier przygotowałem test. Moje uzasadnienie: mniejsza przestrzeń dla przeglądarki do dopasowywania selektorów oznacza szybsze wyszukiwanie.
W moim eksperymencie WebKit trwa obecnie ok.1, 5–2 razy dłużej niż nieużywanie narzędzia :scope
. Kurza twarz! Po naprawieniu strony crbug.com/222028 użycie jej teoretycznie powinno spowodować nieznaczne zwiększenie wydajności niż jej nieużywanie.