ما الغرض من الفئة الزائفة للنطاق في CSS؟

يتم تحديد :scope في أدوات اختيار لغة CSS 4 على النحو التالي:

يشير ذلك المصطلح إلى فئة زائفة تمثّل أي عنصر مُدرَج في مجموعة العناصر المرجعية السياقية. هذه هي مجموعة عناصر (يُحتمَل أن تكون فارغة) محدّدة صراحةً، مثل تلك المحدّدة في السمة querySelector()، أو العنصر الرئيسي للعنصر <style scoped>. ويُستخدَم هذا العنصر "لتحديد نطاق" أداة الاختيار بحيث تتطابق فقط مع شجرة فرعية.

مثال على استخدام ذلك ضمن <style scoped> (مزيد من المعلومات):

<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>

يؤدي هذا الإجراء إلى تلوين عناصر li في أول ul باللون الأحمر، وبسبب القاعدة :scope، يضع حدًا حول ul. وذلك لأنّه في سياق <style scoped> هذه، تتطابق السمة ul مع :scope. إنه السياق المحلي. إذا أضفنا قاعدة :scope في عنصر <style> الخارجي، ستتطابق مع المستند بالكامل. تعادل في الأساس :root.

العناصر السياقية

ربما تكون على دراية بالإصدار Element من querySelector() وquerySelectorAll(). وبدلاً من الاستعلام عن المستند بأكمله، يمكنك تقييد مجموعة النتائج إلى عنصر سياقي:

<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>

عند استدعاء هذه الأحداث، يعرض المتصفّح NodeList الذي تتم فلترته لتضمين مجموعة العُقد التي تتطابق مع أ.) فقط والتي تتطابق مع أداة الاختيار وب.) والتي هي أيضًا تابعة لعنصر السياق. لذلك في المثال الثاني، يعثر المتصفّح على جميع عناصر a، ثم يفلتر العناصر غير المضمّنة في العنصر scope. هذا الأمر مفيد، إلا أنّه قد يؤدي إلى سلوك غريب إذا لم تكُن حذرًا. تابع القراءة.

عندما يحدث خطأ في querySelector

هناك نقطة مهمة في مواصفات أدوات الاختيار والتي غالبًا ما يغفلها المستخدمون. حتى عند استدعاء querySelector[All]() على عنصر، ستظل أدوات الاختيار مقيّمة في سياق المستند بأكمله. هذا يعني أنه يمكن أن تحدث أشياء غير متوقعة:

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

رائع. في المثال الأول، ul هو العنصر الخاص بي، ولكنني ما زلتُ قادرًا على استخدامه ومطابقة العُقد. وفي العنصر الثاني، لا يكون body عنصرًا تابعًا للعنصر الخاص بي، ولكن لا تزال "body ul a" مطابقة. وكلاهما مربك ولا تتوقعه.

الأمر يستحق إجراء مقارنة مع jQuery هنا، والذي يتخذ النهج الصحيح ويفعل ما تتوقعه:

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

...أدخِل :scope لحل هذه المشاكل الدلالية.

إصلاح querySelector باستخدام نطاق :scope

WebKit حصل مؤخرًا على دعم لاستخدام الفئة الزائفة :scope في querySelector[All](). ويمكنك اختباره في Chrome Canary 27.

يمكنك استخدامه حصر أدوات الاختيار على عنصر سياق. لنشاهد مثالاً. في ما يلي، يتم استخدام :scope من أجل "نطاق" أداة الاختيار إلى الشجرة الفرعية لعنصر النطاق. هذا صحيح، قلت النطاق ثلاث مرات!

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

يؤدي استخدام :scope إلى جعل دلالات الطُرق querySelector() أكثر قابلية للتوقّع ومتوافقة مع الإجراءات الحالية الأخرى، مثل jQuery.

هل هذا هو الأداء الأفضل؟

ليس بعد :(

كنت فضوليًا لمعرفة ما إذا كان استخدام :scope في qS/qSA يؤدي إلى تعزيز الأداء. لذلك... مثل مهندس جيد، أعددتُ اختبارًا. سبب ذلك هو أنّ مساحة العرض الأقل في المتصفّح لإجراء مطابقة أدوات الاختيار تعني عمليات بحث أسرع.

في تجربتي، تستغرق WebKit حاليًا حوالي 1.5-2 مرة أطول من عدم استخدام :scope. دراتس! عندما يتم إصلاح crbug.com/222028، من المفترض أن يؤدي استخدامه نظريًا إلى تحسين الأداء قليلاً بدلاً من عدم استخدامه.