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

:scope ให้คำจำกัดความในตัวเลือก CSS 4 เป็น

คลาส Pseudo ซึ่งแสดงถึงองค์ประกอบที่อยู่ในชุดองค์ประกอบการอ้างอิงตามบริบท นี่คือชุดองค์ประกอบ (อาจว่างเปล่า) ที่ระบุอย่างชัดเจน เช่น ที่ระบุโดย 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

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

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

คุณควรเปรียบเทียบกับ jQuery ที่นี่ ซึ่งจะใช้แนวทางที่เหมาะสมและทำสิ่งที่คุณต้องการ:

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

...ป้อน :scope เพื่อแก้โจทย์เกี่ยวกับความหมายเหล่านี้

การแก้ไข querySelector ด้วย :scope

WebKit เพิ่งเปิดตัวการรองรับการใช้คลาส Pseudo-class ของ :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 ใช้เวลานานกว่า :scope ประมาณ 1.5-2 เท่า ดราม่า! เมื่อ crbug.com/222028 ได้รับการแก้ไข การใช้เทมเพลตนี้น่าจะช่วยเพิ่มประสิทธิภาพให้คุณเล็กน้อยแทนที่จะใช้งานจริง