Custom Elements는 사용자 HTML Element를 만들게 해준다. 그리고 이는 DOM의 모든 기능을 다 사용 할 수 있다.
기본적으로 두 가지 타입으로 생성한다.
이렇게 생성한 Element는 Lifecycle callback을 class 안에 정의하여 특정 시점에 동작 하도록 한다.
class MyElement extends HTMLElement {
constructor() {
// 항상 super를 호출 해야 한다.
super();
this.innerHTML = `<h1>This is My Element</h1>`
}
}
customElements.define('my-element', MyElement);
customElements.define에서 정의할 때 아래 사항을 꼭 유념 해야 한다.
Name for the new custom element. Note that custom element names must contain a
hyphen
. by-MDN
constructor 메서드 안에 this
는 customElements를 가리킨다. <my-element>
를 사용해 보면 <h1>
Element가 생성 되고 This is My Element
가 표현 된다.
먼저 상속할 Element를 extends 하여 class를 정의 한다.
class MyButton extends HTMLInputElement {
constructor() {
super();
this.style.border = '1px solid';
this.addEventListender('click', (e) => e.preventDefault());
}
}
정의한 사용자 요소를 등록합니다. 이때 상속한 Element를 인수로 넘겨 준다.
customElements.define("my-button", MyButton, {
extends: "button",
});
마지막으로 <button>
사용 시 is
attribute에 my-button
을 사용자 요소로 사용함을 알려 준다.
<button is='my-button'>Click</button>
custom component가 생성되고 삭제 되기 까지 네 가지 상태에 따른 별도의 callback을 정의 할 수 있습니다. MDN에 따르면 아래와 같은 주기를 가진다.
connectedCallback
: “사용자 정의 요소가 문서에 연결된 요소에 추가될 때마다 호출됩니다. 이것은 노드가 이동 될 때마다 발생할 것이며, 요소의 내용이 완전히 해석되기 전에 발생할 지도 모릅니다.”
disconnectedCallback
: “사용자 정의 요소가 document DOM에서 연결 해제 되었을 때 마다 호출됩니다.”
adoptedCallback
: ”사용자 정의 요소가 새로운 document로 이동 되었을 때마다 호출됩니다.”
attributeChangedCallback
: “사용자 정의 요소의 특성들 중 하나가 추가되거나, 제거되거나, 변경될 때마다 호출됩니다. 어떤 특성이 변경에 대해 알릴지는 static getobservedAttributes
메서드에서 명시됩니다.”
위 생명 주기 콜백은 보면 React, Vue 등에서 사용했던 componentDidMount
mounted
와 비슷한 모양입니다. 사용법도 아래와 같이 비슷하다.
conntectedCallback() {
console.log('연결 완료');
}
disconnectedCallback() {
console.log('연결 해제 완료');
}
adoptedCallback() {
console.log('Element가 다른 page로 이동 하였습니다.');
}
attributeChangedCallback(name, oldValue, newValue) {
console.log('name 이 변경 되었습니다.');
}
static get observedAttributes() {
// 변경을 관찰하고자 하는 attribute를 나열한다.
// 아래 반환값들이 변경되면 `attributeChangedCallback` callback이 호출된다.
return ['autofocus', 'disabled', 'form', 'value']
}
React, Vue와 같은 컴포넌트 기반 어플리케이션 개발에 유용하다고 생각 된다.
구현하는데 boilerplate가 포함되는 것을 보니 라이브러리가 있을 것으로 생각되어 찾아보니 역시 여러 라이브러리들이 있었다.
https://github.com/material-components/material-web
https://github.com/PolymerElements?page=3
다양한 directive 들과 api, cache관리 방법을 제공해 유용해 보였으나 애초에 vender 의존성을 피하고자 web components를 도입하려는 프로젝트에 과연 필요 할까 하는 생각이 든다.