정보실

웹학교

정보실

html Shadow DOM v1 이해(2)

본문

shadowRoot mod 


Shadow root를 첨부하기 위해 Element.attachShadow() 메서드를 호출 할 때 객체를 인수로 전달하여 섀도 DOM 트리에 대한 캡슐화 모드를 지정해야 합니다. 그렇지 않으면 TypeError가 발생합니다. 오브젝트에는 값이 열리거나 닫힌 모드 특성이 있어야 합니다.


열린 그림자 루트를 사용하면 다음 예제와 같이 호스트 요소의 shadowRoot 속성을 사용하여 루트 외부에서 그림자 루트의 요소에 액세스 할 수 있습니다.


<div><p>Light DOM</p></div>
<div id="host"></div>

<script>
  const elem = document.querySelector('#host');

  // attach an open shadow root to #host
  const shadowRoot = elem.attachShadow({mode: 'open'});

  shadowRoot.innerHTML = `<p>Shadow DOM</p>`;

  // Nodes of an open shadow DOM are accessible
  // from outside the shadow root
  elem.shadowRoot.querySelector('p').innerText = 'Changed from outside the shadow root';
  elem.shadowRoot.querySelector('p').style.color = 'red';
</script>

1*OOc1pkscCQoL9oCwJhS0Cg.png?resize=699%2C256&ssl=1 


그러나 mode 속성 값이 closed 인 경우 루트 외부에서 JavaScript를 사용하여 섀도 루트 요소에 액세스하려고 하면 TypeError가 발생합니다.


<div><p>Light DOM</p></div>
<div id="host"></div>

<script>
  const elem = document.querySelector('#host');

  // attach a closed shadow root to #host
  const shadowRoot = elem.attachShadow({mode: 'closed'});

  shadowRoot.innerHTML = `<p>Shadow DOM</p>`;
 
  elem.shadowRoot.querySelector('p').innerText = 'Now nodes cannot be accessed from outside';
  // => TypeError: Cannot read property 'querySelector' of null 
</script>

mode가 closed로 설정되면 shadowRoot 속성은 null을 반환합니다. null 값에는 속성이나 메서드가 없으므로 querySelector()를 호출하면 TypeError가 발생합니다. 닫힌 섀도우 루트는 일반적으로 브라우저에서 일부 요소의 구현 내부를 JavaScript에서 액세스 할 수 없고 변경할 수 없도록 만드는 데 사용됩니다.


섀도 DOM이 열린 모드인지 닫힌 모드인지 확인하려면 섀도우 루트의 mode 속성을 참조하십시오.


<div id="host"></div>

<script>
  const elem = document.querySelector('#host');
  const shadowRoot = elem.attachShadow({mode: 'closed'});

  console.log(shadowRoot.mode);    // => closed
</script>

표면적으로 닫힌 그림자 DOM은 구성 요소의 그림자 루트를 노출하지 않으려는 웹 구성 요소 작성자에게 매우 유용합니다. 그러나 실제로 닫힌 그림자 DOM을 우회 하는 것은 어렵지 않습니다. 일반적으로 섀도우 DOM을 완전히 숨기려면 많은 노력이 필요합니다.


모든 HTML 요소가 shadow DOM을 호스팅 할 수있는 것은 아닙니다 


제한된 요소 세트 만 shadow DOM을 호스팅 할 수 있습니다. 다음 표는 지원되는 요소를 보여줍니다.


+----------------+----------------+----------------+
|    article     |      aside     |   blockquote   |
+----------------+----------------+----------------+
|     body       |       div      |     footer     |
+----------------+----------------+----------------+
|      h1        |       h2       |       h3       |
+----------------+----------------+----------------+
|      h4        |       h5       |       h6       |
+----------------+----------------+----------------+
|    header      |      main      |      nav       |
+----------------+----------------+----------------+
|      p         |     section    |      span      |
+----------------+----------------+----------------+

섀도우 DOM 트리를 다른 요소에 첨부하려고 하면 DOMException 오류가 발생합니다. 예를 들어 :


document.createElement('img').attachShadow({mode: 'open'});    
// => DOMException

<img> 요소를 섀도 호스트로 사용하는 것은 합리적이지 않으므로 이 코드에서 오류가 발생하는 것은 놀라운 일이 아닙니다. DOMException 오류가 발생할 수 있는 또 다른 이유는 브라우저가 이미 해당 요소를 사용하여 새도우 DOM을 호스팅 하기 때문입니다.


브라우저가 일부 요소에 섀도 DOM을 자동으로 첨부 


Shadow DOM은 오랫동안 존재 해 왔으며 브라우저는 이를 사용하여 <input>, <textarea> 및 <video>와 같은 요소의 내부 구조를 숨기고 있습니다.


HTML에서 <video> 요소를 사용하면 브라우저는 기본 브라우저 컨트롤이 포함 된 요소에 섀도 DOM을 자동으로 연결합니다. 그러나 DOM에서 볼 수 있는 유일한 것은 <video> 요소 자체입니다.


1*fkpGG-1YIDngidtJS97xPA.png?resize=938%2C119&ssl=1 


이러한 요소의 섀도우 루트를 Chrome에 표시하려면 Chrome DevTools 설정을 열고 (F1 누름) "요소"섹션에서 "사용자 에이전트 섀도 DOM 표시"를 확인하십시오.


1*ZRlGZWuWGu36sHx3d1KCHg.png?resize=1160%2C437&ssl=1 


"사용자 에이전트 섀도 DOM 표시"옵션을 선택하면 섀도우 루트 노드와 해당 자식이 표시됩니다. 이 옵션을 사용하도록 설정 한 후 동일한 코드를 보는 방법은 다음과 같습니다.


1*dNuxhiSTOp12KxYpuSLNkw.png?resize=1095%2C448&ssl=1 


커스텀 요소에서 shadow DOM 호스팅 


Custom Elements API에 의해 생성 된 사용자 정의 요소는 다른 요소와 마찬가지로 shadow DOM을 호스팅 할 수 있습니다. 다음 예를 고려하십시오.


<my-element></my-element>

<script>
  class MyElement extends HTMLElement {
    constructor() {

      // must be called before the this keyword
      super();

      // attach a shadow root to <my-element>
      const shadowRoot = this.attachShadow({mode: 'open'});

      shadowRoot.innerHTML = `
        <style>p {color: red}</style>
        <p>Hello</p>`;
    }
  }
 
  // register a custom element on the page
  customElements.define('my-element', MyElement);
</script>

이 코드는 섀도 DOM을 호스팅 하는 자율적인 사용자 지정 요소를 만듭니다. 이를 위해 요소 이름을 첫 번째 인수로, 클래스 객체를 두 번째 인수로 사용하여 customElements.define() 메서드를 호출합니다. 이 클래스는 HTMLElement를 확장하고 요소의 동작을 정의합니다.


생성자 내에서 super()는 프로토 타입 체인을 설정하는 데 사용되며 섀도 루트는 사용자 지정 요소에 연결됩니다. 이제 페이지에서 <my-element>를 사용하면 자체 그림자 DOM이 생성됩니다.


1*4iydLrl9S1UXTDZ94CmXxQ.png?resize=806%2C127&ssl=1 


유효한 사용자 정의 요소는 단일 단어 일 수 없으며 이름에 하이픈 (-)이 있어야 합니다. 예를 들어, myelement를 사용자 정의 요소의 이름으로 사용할 수 없으며 DOMException 오류가 발생합니다.



  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 51회 ]  작성일19-08-07 10:41

웹학교