정보실

웹학교

정보실

html 웹 컴포넌트 사용자 정의 요소

본문

사용자 정의 요소에 대한 입문서


맞춤 요소를 사용하면 새로운 HTML 태그를 만들 수 있습니다.


CSS Doodle 라이브러리를 사용할 때까지 이것이 왜 유용한 지 상상할 수 없었습니다. 결국 우리는 이미 많은 태그를 가지고 있습니다.


https://flaviocopes.com/web-components-custom-elements/ 


이 튜토리얼은 작성 당시 표준의 최신 릴리스 인 Custom Elements 버전 1을 다룹니다. 


맞춤 요소를 사용하여 CSS 및 JavaScript와 관련된 맞춤 HTML 태그를 만들 수 있습니다.


React, Angular 또는 Vue와 같은 프레임 워크의 대안은 아니지만 완전히 새로운 개념입니다.


창 전역 객체는 CustomElementRegistry 객체에 대한 액세스를 제공하는 customElements 속성을 노출합니다.


CustomElementRegistry 객체 


이 객체에는 사용자 정의 요소를 등록하고 이미 등록 된 사용자 정의 요소를 쿼리 하는 데 사용할 수 있는 몇 가지 메소드가 있습니다.

  • define() : 새로운 사용자 정의 요소를 정의하는 데 사용
  • get() : 맞춤 요소의 생성자를 가져 오는 데 사용 (존재하지 않은 경우 undefined를 반환)
  • upgrade() : 사용자 정의 요소를 업그레이드하는 방법
  • whenDefined() : 커스텀 요소의 생성자를 얻는 데 사용됩니다. get()과 비슷하지만 promise을 반환하여 항목을 사용할 수 있게 되면 해결됩니다.

맞춤 요소를 만드는 방법 


window.customElements.define() 메소드를 호출하기 전에 HTMLElement 내장 클래스를 확장하는 새 클래스를 작성하여 새 HTML 요소를 정의해야 합니다.

class CustomTitle extends HTMLElement {
	//...
}


클래스 생성자 내에서 Shadow DOM을 사용하여 사용자 정의 CSS, JavaScript 및 HTML을 새 태그에 연결합니다.


이런 식으로 HTML에서 볼 수 있는 것은 모두 태그이지만 많은 기능을 캡슐화 합니다.


생성자를 초기화하여 시작합니다 :

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    //...
  }
}


그런 다음 mode 속성이 'open'으로 설정된 객체를 전달하여 HTMLElement의 attachShadow() 메서드를 호출합니다. 이 속성은 섀도 DOM에 대한 캡슐화 모드를 설정합니다. 열린 경우 요소의 shadowRoot 속성에 액세스 할 수 있습니다. 닫혀 있으면 할 수 없습니다.


그렇게 하는 방법은 다음과 같습니다.

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    //...
  }
}

일부 예제에서는 const shadowRoot = this.attachShadow (/ * ... * /) 구문을 사용하지만 this.shadowRoot를 호출하여 해당 객체를 항상 참조 할 수 있으므로 mode를 closed로 설정하지 않으면 피할 수 있습니다.


innerHTML을 설정하기 위해 지금 할 작업은 다음과 같습니다.

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <h1>My Custom Title!</h1>
    `
  }
}

innerHTML 속성 내에 하나의 태그로 제한되지 않고 원하는 만큼 태그를 추가 할 수 있습니다 


이제 새로 정의 된 요소를 window.customElements에 추가합니다.

window.customElements.define('custom-title', CustomTitle)


페이지에서 <custom-title> </ custom-title> 사용자 정의 요소를 사용할 수 있습니다!


참고 : 자체 폐쇄 태그를 사용할 수 없습니다 (즉,이 <custom-title />은 표준에서 허용되지 않습니다) 


태그 이름에-대시가 있습니다. 맞춤 요소에는 대시를 사용해야 합니다. 이를 통해 맞춤 태그에서 내장 태그를 감지 할 수 있습니다.


이제 페이지에 이 요소가 있으며 다른 태그로 수행 할 수 있는 작업을 수행 할 수 있습니다. CSS 및 JavaScript로 대상을 지정하십시오!


요소에 대한 사용자 정의 CSS 제공 


생성자에서 콘텐츠를 정의하는 HTML 태그 외에 스타일 태그를 전달할 수 있으며 그 안에는 사용자 정의 요소 CSS가있을 수 있습니다.

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <style>
        h1 {
          font-size: 7rem;
          color: #000;
          font-family: Helvetica;
          text-align: center;
        }
      </style>
      <h1>My Custom Title!</h1>
    `
  }
}


Codepen에서 생성 한 맞춤 요소 예는 다음과 같습니다.


https://codepen.io/flaviocopes/pen/LKgjzK 


더 짧은 구문 


먼저 클래스를 정의한 다음 window.customElements.define()을 호출하는 대신이 속기 구문을 사용하여 클래스를 인라인으로 정의 할 수도 있습니다.

window.customElements.define('custom-title', class extends HTMLElement {
  constructor() {
    ...
  }
})


자바 스크립트 추가 


CSS와 마찬가지로 JavaScript도 포함 할 수 있습니다.


CSS와 마찬가지로 템플릿 태그에 직접 추가 할 수 없습니다.


여기서는 사용자 정의 요소 생성자에서 클릭 이벤트 리스너를 정의합니다.

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.innerHTML = `
      <h1>My Custom Title!</h1>
    `
    this.addEventListener('click', e => {
      alert('clicked!')
    })
  }
}


대안 : 템플릿 사용 


JavaScript 문자열에서 HTML과 CSS를 정의하는 대신 HTML에서 템플릿 태그를 사용하여 ID를 할당 할 수 있습니다.

<template id="custom-title-template">
  <style>
    h1 {
      font-size: 7rem;
      color: #000;
      font-family: Helvetica;
      text-align: center;
    }
  </style>
  <h1>My Custom Title!</h1>
</template>

<custom-title></custom-title>


그런 다음 Custom Element 생성자에서 이를 참조하여 Shadow DOM에 추가 할 수 있습니다.

class CustomTitle extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })
    const tmpl = document.querySelector('#custom-title-template')
    this.shadowRoot.appendChild(tmpl.content.cloneNode(true))
  }
}

window.customElements.define('custom-title', CustomTitle)


코드 펜의 예 :


https://codepen.io/flaviocopes/pen/oramEY 


수명주기 후크 


생성자 외에도 Custom Element 클래스는 요소 수명주기에서 특별한 시간에 실행되는 특수 메소드를 정의 할 수 있습니다.

  • connectedCallback 요소가 DOM에 삽입 될 때
  • disconnectedCallback  요소가 DOM에서 제거 될 때
  • attributeChangedCallback  관찰 된 속성이 변경되거나 추가 또는 제거 된 경우
  • adoptedCallback  요소가 새 문서로 이동 한 경우
class CustomTitle extends HTMLElement {
  constructor() {
    ...
  }
  connectedCallback() {
    ...
  }
  disconnectedCallback() {
    ...
  }
  attributeChangedCallback(attrName, oldVal, newVal) {
    ...
  }
}


attributeChangedCallback()은 3 개의 매개 변수를 가져옵니다.

  • 속성 명
  • 속성의 이전 값
  • 속성의 새로운 값

나는 그것이 관찰 된 속성을 듣는다고 언급했다. 저게 뭐야? observeAttributes 정적 메소드에 의해 반환 된 배열로 정의해야 합니다 :

class CustomTitle extends HTMLElement {
  constructor() {
    ...
  }

  static get observedAttributes() {
    return ['disabled']
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    ...
  }
}


disabled 속성을 관찰하도록 정의했습니다. 이제 JavaScript와 같이 변경되면 disabled를 true로 설정합니다.

document.querySelector('custom-title').disabled = true


attributeChangedCallback()은 매개 변수 세트 'disabled', false, true로 실행됩니다.


참고 : attributeChangedCallback()은 JavaScript를 사용하여 요소에서 호출 할 수 있지만 (알 수 없는 이유가 있기 때문에) 그렇게 하지 않아야 합니다. 브라우저에서 자동으로 호출해야 합니다. 


맞춤 속성 정의 


getter 및 setter를 추가하여 사용자 정의 요소에 대한 사용자 정의 속성을 정의 할 수 있습니다.

class CustomTitle extends HTMLElement {
  static get observedAttributes() {
    return ['mycoolattribute']
  }

  get mycoolattribute() {
    return this.getAttribute('mycoolattribute')
  }

  set mycoolattribute(value) {
    this.setAttribute('mycoolattribute', value)
  }
}


다음은 HTML 요소에 대해 비활성화 된 것처럼 부울 속성 (있는 경우 "참"인 속성)을 정의하는 방법입니다.

class CustomTitle extends HTMLElement {
  static get observedAttributes() {
    return ['booleanattribute']
  }

  get booleanattribute() {
    return this.hasAttribute('booleanattribute')
  }

  set booleanattribute(value) {
    if (value) {
      this.setAttribute('booleanattribute', '')
    } else {
      this.removeAttribute('booleanattribute')
    }
  }
}


아직 정의되지 않은 맞춤 요소의 스타일을 지정하는 방법 


JavaScript가 시작되는 데 약간의 시간이 걸리고 페이지가 로드 되는 즉시 사용자 정의 요소가 정의되지 않을 수 있습니다. 요소가 페이지에 추가 될 때 페이지가 보기 흉하게 다시 레이아웃 될 수 있습니다.


이 문제를 해결하려면 가능한 경우 요소의 높이와 페이드를 설정하는 : not (: defined) CSS 의사 클래스를 추가하십시오.

custom-title:not(:defined) {
 display: block;
 height: 400px;
 opacity: 0;
 transition: opacity 0.5s ease-in-out;
}


모든 브라우저에서 사용할 수 있습니까? 


Firefox, Safari 및 Chrome의 최신 버전에서 지원됩니다. IE는 절대로 하지 않을 것이며, 글을 쓰는 시점의 Edge는 개발에서 그들을 지원합니다.


polyfill을 사용하여 이전 브라우저에도 더 나은 지원을 추가 할 수 있습니다.



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

페이지 정보

조회 45회 ]  작성일19-08-20 09:39

웹학교