: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>
這會為第一個 ul
紅色的 li
元素加上顏色,並基於 :scope
規則,在 ul
周圍加上邊框。這是因為在此 <style scoped>
中,ul
與 :scope
相符。貼近當地狀況。如果我們在外部 <style>
中新增 :scope
規則,則會與整份文件相符。基本上等同於 :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.) 符合選取器的一組節點,且 b.) 也是結構定義元素的子系。在第二個範例中,瀏覽器會找出所有 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
即可解決這些語意模糊問題。
使用 :scope 修正 querySelector
WebKit 最近推出支援,以在 querySelector[All]()
中使用 :scope
虛擬類別。您可以在 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。
提升成效?
尚未生效 :(
我想知道在 qS/qSA 中使用 :scope
是否能大幅提升效能。所以...就像是一位優秀的工程師,我一起提出了「測試」了。我的原因:讓瀏覽器進行選取器比對的途徑越少,查詢速度就越快。
在我的實驗中,WebKit 目前使用 :scope
的時間比未使用 :scope
大約 1.5 到 2 倍。乾杯!在修正 crbug.com/222028 後,理論上應該可以稍微提升效能,而不使用。