Lớp giả của CSS :scope dùng để làm gì?

:scope được xác định trong Bộ chọn CSS 4 như sau:

Một lớp giả đại diện cho bất kỳ phần tử nào trong tập hợp phần tử tham chiếu theo bối cảnh. Đây là một tập hợp các phần tử được chỉ định rõ ràng (có thể trống), chẳng hạn như tập hợp do querySelector() chỉ định hoặc phần tử mẹ của phần tử <style scoped>, được dùng để "phạm vi" một bộ chọn để bộ chọn đó chỉ khớp trong một cây con.

Ví dụ về cách sử dụng thuộc tính này trong <style scoped> (thông tin khác):

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

Thao tác này sẽ tô màu các phần tử li trong ul đầu tiên và đặt một đường viền xung quanh ul theo quy tắc :scope. Đó là vì trong ngữ cảnh của <style scoped> này, ul khớp với :scope. Đó là ngữ cảnh cục bộ. Nếu chúng ta thêm quy tắc :scope trong <style> bên ngoài, quy tắc này sẽ khớp với toàn bộ tài liệu. Về cơ bản, tương đương với :root.

Phần tử theo ngữ cảnh

Có thể bạn đã biết phiên bản Element của querySelector()querySelectorAll(). Thay vì truy vấn toàn bộ tài liệu, bạn có thể hạn chế tập hợp kết quả thành một phần tử theo ngữ cảnh:

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

Khi các hàm này được gọi, trình duyệt sẽ trả về một NodeList được lọc để chỉ bao gồm tập hợp các nút a.) khớp với bộ chọn và b.) cũng là phần tử con của phần tử ngữ cảnh. Vì vậy, trong ví dụ thứ hai, trình duyệt sẽ tìm tất cả phần tử a, sau đó lọc ra những phần tử không có trong phần tử scope. Cách này hoạt động, nhưng có thể dẫn đến một số hành vi kỳ lạ nếu bạn không cẩn thận. Hãy đọc thêm.

Khi querySelector gặp lỗi

Có một điểm thực sự quan trọng trong thông số kỹ thuật của bộ chọn mà mọi người thường bỏ qua. Ngay cả khi querySelector[All]() được gọi trên một phần tử, các bộ chọn vẫn đánh giá trong ngữ cảnh của toàn bộ tài liệu. Điều này có nghĩa là những điều không lường trước có thể xảy ra:

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

Ôi trời ơi! Trong ví dụ đầu tiên, ul phần tử của tôi, nhưng tôi vẫn có thể sử dụng phần tử này và so khớp các nút. Ở phần thứ hai, body thậm chí không phải là thành phần con của phần tử của tôi, nhưng "body ul a" vẫn khớp. Cả hai cách này đều gây nhầm lẫn và không như bạn mong đợi.

Nên so sánh với jQuery tại đây, phương pháp này sẽ sử dụng phương pháp phù hợp và thực hiện những gì bạn mong đợi:

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

…hãy nhập :scope để giải quyết những vấn đề ngữ nghĩa này.

Sửa querySelector bằng :scope

WebKit gần đây đã ra mắt tính năng hỗ trợ sử dụng lớp giả :scope trong querySelector[All](). Bạn có thể kiểm tra hoạt động này trong Chrome Canary 27.

Bạn có thể sử dụng thuộc tính này để hạn chế bộ chọn thành phần ngữ cảnh. Hãy xem một ví dụ. Trong ví dụ sau, :scope được dùng để "xác định phạm vi" bộ chọn theo cây con của phần tử phạm vi. Đúng vậy, tôi đã nói phạm vi ba lần!

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

Việc sử dụng :scope giúp ngữ nghĩa của các phương thức querySelector() dễ dự đoán hơn và phù hợp với những gì các phương thức khác như jQuery đang làm.

Hiệu suất thắng?

Chưa :(

Tôi muốn biết liệu việc sử dụng :scope trong qS/qSA có giúp tăng hiệu suất hay không. Vì vậy, như một kỹ sư giỏi, tôi đã tạo một bài kiểm thử. Lý do: trình duyệt có ít khu vực để so khớp bộ chọn hơn đồng nghĩa với việc tra cứu nhanh hơn.

Trong thử nghiệm của tôi, WebKit hiện mất nhiều thời gian hơn khoảng 1,5 đến 2 lần so với khi không sử dụng :scope. Trời ơi! Khi crbug.com/222028 được khắc phục, về lý thuyết, việc sử dụng trang web này sẽ giúp bạn cải thiện hiệu suất một chút so với việc không sử dụng.