CSS :scope pseudo-class มีไว้เพื่ออะไร

: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 สีแดง และจะเพิ่มเส้นขอบรอบๆ ul เนื่องจากกฎ :scope นั่นเป็นเพราะในบริบทของ <style scoped> นี้ ul ตรงกับ :scope บริบทในเครื่อง หากเราเพิ่มกฎ :scope ใน <style> ภายนอก กฎดังกล่าวจะจับคู่กับทั้งเอกสาร โดยพื้นฐานแล้ว จะเทียบเท่ากับ :root

องค์ประกอบตามบริบท

คุณน่าจะรู้จัก querySelector() และ querySelectorAll() เวอร์ชัน Element แล้ว คุณสามารถจํากัดชุดผลลัพธ์ให้แสดงเฉพาะองค์ประกอบตามบริบทแทนการค้นหาทั้งเอกสารได้ ดังนี้

<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 ที่กรองแล้วให้รวมเฉพาะชุดของโหนดที่ ก.) ตรงกับตัวเลือก และ ข.) ซึ่งเป็นองค์ประกอบสืบทอดขององค์ประกอบบริบทด้วย ดังนั้นในตัวอย่างที่ 2 เบราว์เซอร์จะค้นหาองค์ประกอบ a ทั้งหมด จากนั้นกรององค์ประกอบที่ไม่ได้อยู่ในองค์ประกอบ scope ออก วิธีนี้ได้ผล แต่อาจทําให้อุปกรณ์ทำงานแปลกๆ ได้หากไม่ระมัดระวัง อ่านต่อไป

เมื่อ querySelector ทำงานผิดพลาด

มีประเด็นสำคัญจริงๆ ในข้อกำหนดเกี่ยวกับตัวเลือกที่ผู้คนมักมองข้าม แม้ว่าจะมีการเรียกใช้ querySelector[All]() ในองค์ประกอบ แต่ตัวเลือกจะยังคงประเมินในบริบทของทั้งเอกสาร ซึ่งหมายความว่าอาจเกิดเหตุการณ์ที่ไม่คาดคิด ดังนี้

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

เหลือเชื่อ! ในตัวอย่างแรก ul is องค์ประกอบของฉัน แต่ฉันยังคงใช้และจับคู่โหนดได้ ในตัวอย่างที่ 2 body ไม่ได้เป็นองค์ประกอบสืบทอดจากองค์ประกอบของฉัน แต่ "body ul a" ยังคงตรงกัน ทั้ง 2 อย่างนี้ทำให้เกิดความสับสนและไม่ตรงกับที่คุณคาดหวัง

เราขอเปรียบเทียบกับ 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 ใช้เพื่อ "กําหนดขอบเขต" ตัวเลือกไปยังต้นไม้ย่อยขององค์ประกอบขอบเขต ใช่แล้ว ฉันพูดขอบเขต 3 ครั้ง

    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 Drats เมื่อ crbug.com/222028 ได้รับการแก้ไขแล้ว ในทางทฤษฎีแล้ว การใช้ฟีเจอร์นี้ควรช่วยเพิ่มประสิทธิภาพได้เล็กน้อยเมื่อเทียบกับการไม่ใช้