: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
와 동일합니다.
문맥 요소
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>
이러한 메서드가 호출되면 브라우저는 a.) 선택기와 일치하는 노드 집합 및 b.) 컨텍스트 요소의 하위 요소이기도 한 노드 집합만 포함하도록 필터링된 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
을 입력합니다.
: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
를 사용하지 않는 것보다 최대 1.5~2배 더 오래 걸립니다. 이런! crbug.com/222028이 수정되면 사용하지 않는 것보다 이론적으로 성능이 약간 향상됩니다.