CSS :scope sözde sınıfının amacı nedir?

:scope, CSS Seçiciler 4'te şu şekilde tanımlanır:

Bağlamsal referans öğesi grubundaki herhangi bir öğeyi temsil eden sözde sınıf. Bu, querySelector() tarafından belirtilenler gibi açıkça belirtilmiş bir öğe grubu (büyük olasılıkla boş) veya bir <style scoped> öğesinin üst öğesidir ve bir seçiciyi yalnızca bir alt ağacın içinde eşleşecek şekilde "kapsama almak" için kullanılır.

Bunun kullanımına <style scoped> içinde bir örnek verilebilir (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 işlem, ilk ul içindeki li öğelerini kırmızıya boyatır ve :scope kuralı nedeniyle ul öğesinin etrafına bir kenarlık yerleştirir. Bunun nedeni, bu <style scoped> bağlamında ul değerinin :scope ile eşleşmesidir. Yerel bağlam. Dış <style> öğesine :scope kuralı eklersek tüm dokümanla eşleşir. Temelde :root ile eşdeğerdir.

Bağlamsal öğeler

Büyük olasılıkla querySelector() ve querySelectorAll() Element sürümlerini biliyorsunuz. 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çici ile eşleşen ve b.) ile eşleşen ve aynı zamanda bağlam öğesinin alt öğeleri olan düğüm grubunu içerecek şekilde filtrelenmiş bir NodeList döndürür. Dolayısıyla, ikinci örnekte tarayıcı tüm a öğelerini bulur ve ardından scope öğesinde olmayan öğeleri filtreler. Bu yöntem işe yarıyor ancak dikkatli olmazsanız tuhaf davranışlara neden olabilir. Okumaya devam edin.

querySelector yanlış gittiğinde

Seçiciler spesifikasyonunda kullanıcıların genellikle göz ardı ettiği gerçekten önemli bir nokta vardır. Bir öğede querySelector[All]() çağrılsa bile seçiciler, tüm belgenin bağlamında değerlendirmeye devam eder. Bu durum, beklenmedik durumların ortaya çıkabileceği anlamına gelir:

    scope.querySelectorAll('ul a').length); // 1
    scope.querySelectorAll('body ul a').length); // 1

Vay canına! İlk örnekte, ul öğemdir, ancak yine de onu kullanabilirim ve düğümlerle eşleşir. İkincisinde, body benim öğemin bir alt öğesi bile değil, ancak "body ul a" hâlâ eşleşiyor. Bunların ikisi de kafa karıştırıcıdır ve beklediğiniz gibi değildir.

Burada, doğru yaklaşımı uygulayan ve beklediğinizi yapan jQuery ile karşılaştırma yapmak yerinde olacaktır:

    $(scope).find('ul a').length // 0
    $(scope).find('body ul a').length // 0

...bu anlamsal maskaralıkları çözmek için :scope yazın.

:scope ile querySelector'ı düzeltme

WebKit, kısa bir süre önce querySelector[All]() ürününde :scope sözde sınıfının kullanımı için destek aldı. Bu özelliği Chrome Canary 27'de test edebilirsiniz.

Seçicileri bir bağlam öğesiyle sınırlandırabilirsiniz. Bir örnekle açıklayalım. Aşağıda :scope, seçiciyi kapsam öğesinin alt ağacının kapsamına "kapsama almak" için kullanılır. Doğru, üç kez kapsam dedim.

    scope.querySelectorAll(':scope ul a').length); // 0
    scope.querySelectorAll(':scope body ul a').length); // 0
    scope.querySelectorAll(':scope a').length); // 1

:scope kullanımı, querySelector() yöntemlerinin anlamını biraz daha tahmin edilebilir ve jQuery gibi diğer yöntemlere uygun hale getirir.

Peki, performans açısından kazançlı mı?

Henüz değil :(

QS/qSA'da :scope kullanmanın performansı artırıp artırmadığını merak ediyorum. Ben de iyi bir mühendis gibi bir test yaptım. Gerekçe: Tarayıcının seçici eşleştirme yapması için daha az yüzey alanı olması, aramaların daha hızlı olacağı anlamına gelir.

Denememde, WebKit şu an :scope kullanmamaya göre yaklaşık 1,5-2 kat daha uzun sürüyor. Drats! crbug.com/222028 adresi düzeltildiğinde, bu adresi kullanmamak yerine bu adresi kullanmak teorik olarak size biraz performans artışı sağlayacaktır.