:scope
, CSS Seçicileri 4'te şu şekilde tanımlanır:
Bağlamsal referans öğesi grubundaki tüm öğeleri temsil eden bir sözde sınıf. Bu,
querySelector()
tarafından belirtilen veya bir<style scoped>
öğesinin üst öğesi gibi açıkça belirtilen bir (boş olabilecek) öğe grubudur. Seçicinin yalnızca bir alt ağaçta eşleşmesi için "kapsamını" belirlemek amacıyla kullanılır.
Bu özelliğin <style scoped>
içinde kullanıldığı bir örnek (daha fazla bilgi):
<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>
Bu, ilk ul
içindeki li
öğelerini kırmızıya boyar ve :scope
kuralı nedeniyle ul
etrafına bir kenarlık ekler. Bunun nedeni, bu <style scoped>
bağlamında ul
'ın :scope
ile eşleşmesidir. Yerel bağlamdır. Dış <style>
içine bir :scope
kuralı eklersek bu kural, belgenin tamamıyla eşleşir. Esasen :root
ile eşdeğerdir.
Bağlamsal öğeler
querySelector()
ve querySelectorAll()
'in Element
sürümünü muhtemelen biliyorsunuzdur. Dokümanın tamamını sorgulamak yerine sonuç kümesini bağlamsal bir öğeyle kısıtlayabilirsiniz:
<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>
Bunlar çağrıldığında tarayıcı, yalnızca a.) seçiciyle eşleşen ve b.) aynı zamanda içerik öğesinin alt öğeleri olan düğüm kümesini içerecek şekilde filtrelenmiş bir NodeList
döndürür. Dolayısıyla ikinci örnekte tarayıcı tüm a
öğelerini bulur, ardından scope
öğesinde olmayanları filtreler. Bu yöntem işe yarar ancak dikkatli olmazsanız tuhaf davranışlarla karşılaşabilirsiniz. Okumaya devam edin.
querySelector yanlış gittiğinde
Seçiciler spesifikasyonunda, kullanıcıların genellikle gözden kaçırdığı çok önemli bir nokta vardır. Bir öğede querySelector[All]()
çağrıldığında bile seçiciler, belgenin tamamı bağlamında değerlendirilmeye devam eder. Bu durumda beklenmedik şeyler olabilir:
scope.querySelectorAll('ul a').length); // 1
scope.querySelectorAll('body ul a').length); // 1
WTF! İlk örnekte ul
öğemdir ancak yine de kullanabilir ve düğümlerle eşleştirebilirim. İkinci örnekte body
, öğemin alt öğesi bile değil ancak "body ul a
" yine de eşleşiyor. Bu iki durum da kafa karıştırıcıdır ve beklediğiniz gibi değildir.
Doğru yaklaşımı benimseyen ve beklediğinizi yapan jQuery ile karşılaştırma yapmak faydalı olacaktır:
$(scope).find('ul a').length // 0
$(scope).find('body ul a').length // 0
…bu anlamsal saçmalıkları çözmek için :scope
yazın.
querySelector'i :scope ile düzeltme
WebKit, querySelector[All]()
'te :scope
sözde sınıfını kullanma desteğini yakın zamanda kullanıma sundu. Bu özelliği Chrome Canary 27'de test edebilirsiniz.
Seçicileri bir bağlam öğesiyle sınırlamak için kullanabilirsiniz. Bir örnekle açıklayalım. Aşağıda, seçiciyi kapsam öğesinin alt ağacına "kapsamlamak" için :scope
kullanılır. Doğru, kapsamı üç kez söyledim.
scope.querySelectorAll(':scope ul a').length); // 0
scope.querySelectorAll(':scope body ul a').length); // 0
scope.querySelectorAll(':scope a').length); // 1
:scope
kullanmak, querySelector()
yöntemlerinin anlamını biraz daha tahmin edilebilir hale getirir ve jQuery gibi diğerlerinin zaten yaptığıyla uyumlu hale getirir.
Performans kazancı mı?
Henüz değil :(
qS/qSA'da :scope
kullanılmasının performansı artırıp artırmadığını merak ediyorum. İyi bir mühendis gibi bir test hazırladım. Gerekçem: Tarayıcının seçici eşleştirmesi için daha az yüzey alanı, daha hızlı aramalar anlamına gelir.
Denememizde WebKit, şu anda :scope
kullanmamaya kıyasla yaklaşık 1,5-2 kat daha uzun sürüyor. Lanet olsun! crbug.com/222028 düzeltildiğinde, bu özelliği kullanmamak yerine kullanmak teorik olarak size performans açısından küçük bir artış sağlayabilir.