웹 컴포넌트 사용자 정의 요소
본문
사용자 정의 요소에 대한 입문서
맞춤 요소를 사용하면 새로운 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을 사용하여 이전 브라우저에도 더 나은 지원을 추가 할 수 있습니다.
- 이전글HTML`a` 태그 19.08.20
- 다음글웹 페이지에서 스크롤하는 방법 19.08.20