SPA Framework의 Router 구현해보기 - (2)

박춘화·2022년 3월 9일
0

Router

router.js

import DetailPage from "./pages/DetailPage";
import MainPage from "./pages/MainPage";
import NotFoundPage from "./pages/NotFoundPage";

class Router {
  constructor(routes) {
    this.routes = routes;
    this.routeList = Object.keys(this.routes);
  }
  
  // 경로가 바뀔 때 실행될 리스너 함수를 등록하는 메서드
  registerListener(listener) {
    window.addEventListener("changePath", listener);
  }

  // 라우터를 통한 URL 이동 시에 URL의 변경을 애플리케이션에 알리는 임의의 이벤트 'changePath' 이벤트를 발생시키는 메서드
  go(path) {
    history.pushState(null, null, path);
    window.dispatchEvent(new Event("changePath"));
  }
}

const routes = {
  "/": MainPage,
  "/detail": DetailPage,
  "/404": NotFoundPage
};

const router = new Router(routes);

export default router;

Router를 App에 적용시켜보자.

App.js

import router from "./router";

export default function App({ $parent }) {
  // URL 변경 시에 애플리케이션 내부 DOM Element를 초기화
  this.initApp = () => {
    $parent.innerHTML = "";
  };

  this.render = () => {
    this.initApp(); // 애플리케이션 내부 DOM Element를 초기화

    const { pathname } = location;

    // 변경된 URL이 라우터에 등록된 URL이 아닐 경우
    if (!router.routeList.includes(pathname)) {
      // 404 페이지로 이동
      history.pushState(null, null, "/404");
      new router.routes["/404"]({ $parent });
    } else {
      // 변경된 URL이 라우터에 등록된 URL일 경우 해당 페이지로 이동
      new router.routes[pathname]({ $parent });
    }
  };

  // 라우터를 통한 페이지 이동 시에 애플리케이션이 렌더링 되도록 'changePath' 이벤트에 렌더링 함수를 리스너 함수로 등록
  router.registerListener(this.render);

  this.render();
}

이제 Router를 통한 페이지 이동을 테스트해보자. 메인 페이지와 상세 페이지에 각각 다른 페이지로 이동하는 버튼을 추가했다.

MainPage.js

import router from "../router";

export default function MainPage({ $parent }) {
  const $page = document.createElement("div");

  $parent.appendChild($page);

  this.render = () => {
    $page.innerHTML = `
    <h1>메인 페이지입니다.</h1>
    <button id="to-detail-btn">상세 페이지로</button>
    `;

    document
      .querySelector("button#to-detail-btn")
      .addEventListener("click", (e) => {
        router.go("/detail");
      });
  };

  this.render();
}

DetailPage.js

import router from "../router";

export default function DetailPage({ $parent }) {
  const $page = document.createElement("div");

  $parent.appendChild($page);

  this.render = () => {
    $page.innerHTML = `
    <h1>상세 페이지입니다.</h1>
    <button id="to-main-btn">메인 페이지로</button>
    `;

    document
      .querySelector("button#to-main-btn")
      .addEventListener("click", (e) => {
        router.go("/");
      });
  };

  this.render();
}

History.pushState를 활용하여 SPA Framework의 Router를 구현했다. 예제를 통해 제대로 작동하는지 확인해보자.

예제

https://piuvoo.csb.app/

참고 자료

profile
함께 성장하는 개발자

0개의 댓글