바닐라 자바스크립트로 웹 컴포넌트 구현하기

Jeremy·2023년 3월 15일
0

왜 자스로 웹 컴포넌트를 만들게 되었나..

html, css, javascript를 활용한 SPA 만들기 두 번째 미션을 진행했다.

첫 번째 미션에서는 흔히 알려진 템플릿 메서드를 활용하여 구현했었는데 그렇게 구현하다보니 렌더링 최적화를 구현하는데 많은 어려움을 겪었고 오버라이딩 되는 문제가 발생했다. 그리고 상위컴포넌트의 상태를 변경하기 위해서는 setState를 props로 this 바인딩하여 넘겨주다보니 props Driling 문제도 발생했다.

첫 번째 미션을 어떻게 구현했는지 보고 싶다면 여기를 참고하라.

그래서 이번 미션에서는 Custom Element를 활용한 웹 컴포넌트를 만들어보기로 했다.

커스텀 이벤트를 생성하여 이벤트 버블링으로 props Driling없이 상위 컴포넌트에 인자를 넘겨줄 수 있다는 장점이 매력적이었기 때문이다.

그리고 최근에 리액트대신 자바스크립트 웹 컴포넌트를 많이 사용한다고들해서 한 번쯤은 경험해보고 싶었다.

그래서 어케 쓰노..?

두 번째 SPA 미션

웹 컴포넌트 만들기

export default class MovieCard extends HTMLElement {
  get title() {
    return this.getAttribute("title");
  }

  get rating() {
    return this.getAttribute("rating");
  }

  get poster() {
    return this.getAttribute("poster");
  }

  connectedCallback() {
    this.innerHTML = `
    <li>
       <a href="#">
         <div class="item-card">
           <img
             class="item-thumbnail"
             src="https://image.tmdb.org/t/p/w220_and_h330_face${this.poster}"
             loading="lazy"
             alt="${this.title}"
           />
           <p class="item-title">${this.title}</p>
           <p class="item-score">${this.rating}<img src=./star.png alt="별점" /> </p>
         </div>
       </a>
     </li>
       `;
  }
}

customElements.define("movie-card", MovieCard);

이렇게 movie-card라는 컴포넌트를 생성해준다.

movieList.forEach((item) => {
      ItemList.insertAdjacentHTML(
        "beforeend",
        `<movie-card title='${item.title}' poster='${item.poster}' rating='${item.rating}'></movie-card>`
      );
    });

그리고 위처럼 속성을 통해 인자를 넘겨주며 컴포넌트를 활용한다.

이벤트 생성하기

export default class MovieSearch extends HTMLElement {
  connectedCallback() {
    this.innerHTML = /*html*/ `
         <div class="search-box">
          <input type="text" placeholder="검색" />
          <button class="search-button">검색</button>
         </div>
        `;
    this.setEvent();
  }

  setEvent() {
    this.querySelector(".search-button").addEventListener("click", () => {
      const movieName = this.querySelector("input").value;
      this.dispatchEvent(
        new CustomEvent("search-movie", { bubbles: true, detail: movieName })
      );
    });
  }
}

customElements.define("movie-search", MovieSearch);

검색 버튼 클릭시 검색창에 있는 value를 최상위 Element인 App으로 보내주기 위한 코드이다.
검색 버튼을 클릭하면 search-movie라는 커스텀 이벤트로 검색창 value를 detail을 통해 보낼 수 있다.

//App.js

   document.addEventListener("search-movie", (event) => {
      this.#listState = LIST_STATE.SEARCHED;
      this.#page = 1;
      this.#movieName = event.detail;
      this.renderSearchedMovies(event.detail);
    });

클릭이벤트 발생시 App에서 이벤트 버블링으로 이벤트를 감지하여 검색창 value를 event.detail로 받아와 사용할 수 있다.

profile
chill~

0개의 댓글