Custom Elements

class Test extends HTMLElement {
    constructor() {
        // super()를 호출함으로써 시작하여 올바른 프로토타입 체인이 확립되도록 한다.
        super();
    }
    static get observedAttributes() {
        // 모니터링 할 속성 이름
        // 이 메서드는 관찰하기를 원하는 특성들의 이름을 포함하는 배열을 return 해야 한다.
        return ['c', 'l'];
    }
    connectedCallback() {
        // 사용자 정의 요소가 문서에 연결된 요소에 추가될 때마다 호출된다. 
        // 이것은 노드가 이동될 때마다 발생할 것이며, 요소의 내용이 완전히 해석되기 전에 발생할 지도 모른다.
        // DOM에 추가되었다. 렌더링 등의 처리를 하자.
        this.start();
    }
    disconnectedCallback() {
        // 사용자 정의 요소가 document의 DOM에서 연결 해제되었을 때마다 호출된다.
        // DOM에서 제거되었다. 엘리먼트를 정리하는 일을 하자.
        this.stop();
    }
    attributeChangedCallback(name, oldVal, newVal) {
        // 속성이 추가/제거/변경되었다.
        // 어떤 특성이 변경에 대해 알릴지는 static get observedAttributes 메서드에서 명시된다.
    }
    adoptedCallback(oldDoc, newDoc) {
        // 사용자 정의 요소가 새로운 document로 이동되었을 때마다 호출된다.
        // 다른 Document에서 옮겨져 왔다, 자주 쓸 일은 없을 것.
    }
}
customElements.define('test-tag', Test);

js만으로 컴포넌트 단위를 만들 수 있다. 위의 코드처럼 클래스에서 적절한 생명 주기 콜백을 정의하여 사용할  수도 있고

클래스의 인스턴스가 인스턴스화되었을 때 요소가 가질 모든 기능을 클래스 내에 정의할 수도 있다.

tag이름은 규칙이 있다. 하이픈( - ) 을 하나 이상 포함해야하고 대문자는 안되는 듯 하다.

 

class SignUpModal extends HTMLElement {
    connectedCallback() {
        ....
        this.innerHTML = `
        <div id="signup-modal" class="modal">
            <div class="modal-content">
                <h2>회원가입</h2>
                <form id="signup-form" onsubmit="return false;">
                    <label for="email">Email:</label>
                    <input type="email" id="email" name="email"><br><br>
                    <label for="username">Username:</label>
                    <input type="text" id="username" name="username"><br><br>
                    <label for="password">Password:</label>
                    <input type="password" id="password" name="password"><br><br>
                    <button type="submit">가입하기</button>
                </form>
                <button id="signup-modal-close">닫기</button>
            </div>
        </div>
        `;        
        const modal = document.querySelector("#signup-modal");
        const formElem = document.querySelector("#signup-form");
        const closeModalButton = document.querySelector("#signup-modal-close");
        ...
    }
}

위와 같이 connectedCallback에 innerHTML을 통해 사용자 정의 태그를 사용할 수도 있다.

단 connectedCallback의 설명에 "사용자 정의 요소가 문서에 연결된 요소에 추가될 때마다 호출된다. 이것은 노드가 이동될 때마다 발생할 것이며, 요소의 내용이 완전히 해석되기 전에 발생할 지도 모른다."

라는 부분을 주의할 필요가 있다.

참고 자료

https://developer.mozilla.org/ko/docs/Web/API/Web_components/Using_custom_elements

 

사용자 정의 요소 사용하기 - Web API | MDN

웹 컴포넌트 표준의 주요 기능 중 하나는 사용자 정의 페이지 기능을 제공하는 길고 중첩된 요소들의 묶음으로 만족하는 것보다는, HTML 페이지에서 기능을 캡슐화하는 사용자 정의 요소를 생성

developer.mozilla.org

https://velog.io/@design0728/Web-Component-8njgyg44

 

Web Component

자바스크립트 프레임워크들은 다양한 문제를 해결할 강력한 도구이지만, 무거운 덩치는 앱을 무겁게 만들고 리소스를 사용자에게 전가시키며 프레임워크 종속적인 코드를 생산하게 한다. 이러

velog.io

'front-end' 카테고리의 다른 글

react contextMenu 만들기  (0) 2023.08.24
채팅-React.memo()  (0) 2023.08.22
채팅 - Array.prototype.reduce()  (0) 2023.08.22
프론트 상태 관리 Recoil 사용하기  (0) 2023.08.19
webpack ts react boilerplate  (0) 2023.08.18