Shadow Dom – Smashing Magazine과 함께 일합니다
to
각 요소는 하나의 그림자 루트만을 가질 수 있습니다. 일부 요소를 포함합니다 그리고
스크립팅을 통해 액세스 할 수없는 내장 그림자 루트가 이미 있습니다. 활성화하여 개발자 도구로 검사 할 수 있습니다. 사용자 에이전트 Shadow Dom을 보여줍니다 설정, 기본적으로 “꺼짐”입니다.


그림자 루트 생성
Shadow Dom의 이점을 활용하기 전에 먼저 그림자 뿌리 요소에. 이것은 명령 적으로 또는 선언적으로 인스턴스화 될 수 있습니다.
명확한 인스턴스화
JavaScript를 사용하여 그림자 루트를 만들려면 사용하십시오 attachShadow({ mode })
요소에. 그만큼 mode
할 수 있습니다 open
(액세스 허용 element.shadowRoot
) 또는 closed
(외부 스크립트에서 그림자 뿌리를 숨기기).
const host = document.createElement('div');
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = 'Hello from the Shadow DOM!
';
document.body.appendChild(host);
이 예에서는 An을 설정했습니다 open
그림자 뿌리. 즉, 요소의 컨텐츠가 외부에서 액세스 할 수 있으며 다른 DOM 노드와 마찬가지로 쿼리 할 수 있습니다.
host.shadowRoot.querySelector('p'); // selects the paragraph element
외부 스크립트가 내부 구조에 완전히 액세스하는 것을 방지하려면 모드를 설정할 수 있습니다. closed
대신에. 이것은 요소의 원인입니다 shadowRoot
반환 할 재산 null
. 우리는 여전히 우리에게서 액세스 할 수 있습니다 shadow
우리가 만든 범위에서 참조.
shadow.querySelector('p');
이것은 중요한 보안 기능입니다. a closed
Shadow Root, 우리는 악의적 인 행위자가 구성 요소에서 개인 사용자 데이터를 추출 할 수 없다고 확신 할 수 있습니다. 예를 들어, 은행 정보를 보여주는 위젯을 고려하십시오. 아마도 사용자의 계정 번호가 포함되어있을 것입니다. 와 함께 open
Shadow Root, 페이지의 모든 스크립트는 구성 요소로 드릴링하여 내용을 구문 분석 할 수 있습니다. ~ 안에 closed
모드에서는 사용자 만 수동 복사용으로 이러한 종류의 작업을 수행하거나 요소를 검사하여 수행 할 수 있습니다.
나는 제안한다 폐쇄 된 최초의 접근 Shadow Dom과 함께 일할 때. 사용하는 습관을 만드십시오 closed
디버깅하지 않는 한 모드를 피할 수없는 실제 제한을 얻는 데 절대적으로 필요한 경우에만 모드. 이 접근법을 따르면 인스턴스가 open
모드는 실제로 필요합니다.
선언적인 인스턴스화
Shadow Dom을 활용하기 위해 JavaScript를 사용할 필요는 없습니다. 그림자 루트를 등록하는 것은 선언적으로 수행 할 수 있습니다. 중첩 a a
shadowrootmode
지원되는 요소 내부의 속성으로 인해 브라우저가 그림자 루트로 해당 요소를 자동으로 업그레이드하게됩니다. 이러한 방식으로 그림자 루트를 부착하는 것은 JavaScript 비활성화 된 상태에서도 수행 할 수 있습니다.
Declarative Shadow DOM content
다시 말하지만, 이것은 일 수 있습니다 open
또는 closed
. 사용하기 전에 보안 영향을 고려하십시오 open
모드이지만 액세스 할 수 없습니다 closed
이 방법을 사용하지 않는 한 모든 스크립트를 통한 모드 컨텐츠 등기 사용자 정의 요소,이 경우 사용할 수 있습니다 ElementInternals
자동으로 첨부 된 그림자 루트에 액세스하려면 :
class MyWidget extends HTMLElement {
#internals;
#shadowRoot;
constructor() {
super();
this.#internals = this.attachInternals();
this.#shadowRoot = this.#internals.shadowRoot;
}
connectedCallback() {
const p = this.#shadowRoot.querySelector('p')
console.log(p.textContent); // this works
}
};
customElements.define('my-widget', MyWidget);
export { MyWidget };
그림자 dom 구성
그 외에 세 가지 다른 옵션이 있습니다 방법 우리가 통과 할 수 있습니다 Element.attachShadow()
.
Option 1: clonable:true
최근까지 표준 요소에 그림자 뿌리가 부착되어 있고 Node.cloneNode(true)
또는 document.importNode(node,true)
그림자 루트 내용이없는 호스트 요소의 얕은 사본 만 얻을 수 있습니다. 우리가 방금 보았던 예는 실제로 비어 있습니다.
But for a declarative Shadow DOM, this means that each element needs its own template, and they cannot be reused. With this newly-added feature, we can selectively clone components when it’s desirable:
Option 2: serializable:true
이 옵션을 활성화하면 요소의 섀도우 루트 내부의 컨텐츠 표현을 저장할 수 있습니다. 부름 Element.getHTML()
호스트 요소는 모든 중첩 인스턴스를 포함하여 Shadow Dom의 현재 상태의 템플릿 사본을 반환합니다. shadowrootserializable
. 이것은 그림자 루트의 사본을 다른 호스트에 주입하거나 나중에 사용할 수 있도록 캐시하는 데 사용될 수 있습니다.
Chrome에서는 실제로 닫힌 섀도우 루트를 통해 작동 하므로이 기능으로 실수로 사용자 데이터를 유출하는 데주의하십시오. 더 안전한 대안은 a를 사용하는 것입니다 closed
래퍼는 외부 영향으로부터 내용을 보호하면서도 여전히 물건을 유지하면서 open
내부 :
`); this.clonecontent (); } cloneContent () {const nested = this.#shadow.querySelector ( 'Nested-Element'); const snapshot = nested.gethtml ({serializableshadowroots : true}); const temp = document.createElement ( 'div'); temp.sethtmlunsafe (`
알아채다 setHTMLUnsafe()
. 콘텐츠에 포함되어 있기 때문에 거기에 있습니다 강요. 이 방법은 주입 할 때 호출해야합니다 신뢰할 수 있습니다 이 성격의 내용. 사용을 사용하여 템플릿을 삽입합니다
innerHTML
자동 초기화를 그림자 루트로 트리거하지 않습니다.
옵션 3 : : 옵션 3 delegatesFocus:true
이 옵션은 본질적으로 호스트 요소가 내부 컨텐츠. 활성화되면 호스트 또는 호출의 어느 곳에서나 클릭하십시오
.focus()
그것은 커서를 그림자 루트의 첫 번째 초점 요소로 옮길 것입니다. 이것은 또한 적용됩니다 :focus
호스트에 대한 의사 클래스는 양식에 참여하기위한 구성 요소를 만들 때 특히 유용합니다.
이 예제는 초점 대표단만을 보여줍니다. 캡슐화의 이상한 점 중 하나는 양식 제출이 자동으로 연결되어 있지 않다는 것입니다. 즉, 입력의 값이 기본적으로 양식 제출에 있지 않음을 의미합니다. 양식 검증 및 상태는 그림자 Dom에서 전달되지 않습니다. 섀도우 루트 경계가 ARIA를 방해 할 수있는 접근성과 비슷한 연결 문제가 있습니다. 이것들은 우리가 해결할 수있는 형태에 따른 고려 사항입니다. ElementInternals
이것은 다른 기사의 주제이며 대신 Light DOM 양식에 의존 할 수 있는지 의문을 제기합니다.
슬롯 형 컨텐츠
지금까지 우리는 완전히 캡슐화 된 구성 요소 만 살펴 보았습니다. 주요 섀도우 DOM 기능이 사용 중입니다 슬롯 구성 요소의 내부 구조에 콘텐츠를 선택적으로 주입합니다. 각 그림자 루트는 하나를 가질 수 있습니다 기본 (이름 없음)
; 다른 모든 사람은해야합니다 지명. 슬롯의 이름 지정은 구성 요소의 특정 부분을 채울 수있는 컨텐츠와 폴백 컨텐츠를 채울 수 있도록 사용자가 생략 한 슬롯을 채울 수 있습니다.
Fallback Title
A placeholder description.
A Slotted Title
An example of using slots to fill parts of a component.
Foo
Bar
Baz
기본 슬롯도 폴백 컨텐츠를 지원하지만 모든 길 잃은 텍스트 노드는이를 채우게됩니다. 결과적으로 호스트 요소의 마크 업에서 모든 공백을 무너 뜨리는 경우에만 작동합니다.
Fallback Content
슬롯 요소가 방출됩니다 slotchange
이벤트 assignedNodes()
추가 또는 제거됩니다. 이 이벤트는 슬롯이나 노드에 대한 참조가 포함되어 있지 않으므로 이벤트를 이벤트 핸들러에 전달해야합니다.
class SlottedWidget extends HTMLElement {
#internals;
#shadow;
constructor() {
super();
this.#internals = this.attachInternals();
this.#shadow = this.#internals.shadowRoot;
this.configureSlots();
}
configureSlots() {
const slots = this.#shadow.querySelectorAll('slot');
console.log({ slots });
slots.forEach(slot => {
slot.addEventListener('slotchange', () => {
console.log({
changedSlot: slot.name || 'default',
assignedNodes: slot.assignedNodes()
});
});
});
}
}
customElements.define('slotted-widget', SlottedWidget);
다중 요소는 단일 슬롯에 할당 될 수 있으며 slot
속성 또는 스크립팅을 통해 :
const widget = document.querySelector('slotted-widget');
const added = document.createElement('p');
added.textContent="A secondary paragraph added using a named slot.";
added.slot="description";
widget.append(added);
이 예제의 단락은 주인 요소. 슬롯 형 컨텐츠는 실제로 그림자 Dom이 아닌 "Light"Dom에 속합니다. 지금까지 다룬 예제와 달리 이러한 요소는 document
물체:
const widgetTitle = document.querySelector('my-widget [slot=title]');
widgetTitle.textContent="A Different Title";
수업 정의에서 내부적으로 이러한 요소에 액세스하려면 사용하십시오. this.children
또는 this.querySelector
. 만
요소 자체는 내용이 아닌 Shadow Dom을 통해 쿼리 할 수 있습니다.
미스터리에서 숙달까지
이제 알다시피 왜 Shadow Dom을 사용하고 싶을 것입니다. 언제 당신은 그것을 당신의 작업에 포함시켜야합니다 어떻게 지금 당장 사용할 수 있습니다.
그러나 귀하의 웹 구성 요소 여행은 여기서 끝날 수 없습니다. 우리는이 기사에서 마크 업과 스크립팅 만 다루었습니다. 우리는 웹 구성 요소의 또 다른 주요 측면을 만지지 않았습니다. 스타일 캡슐화. 그것은 다른 기사의 우리의 주제가 될 것입니다.

(GG, YK)
Post Comment