라우터 구현

yoon Y·2022년 3월 20일
0

Vanilla Project

목록 보기
11/13

history API를 이용해 url이동시키기

1. 필요한 함수 선언

  • route-push라는 커스텀 이벤트를 발생시키고 이동할 url을 event객체에 할당하는 함수
    // router.ts
    export const push = (nextUrl: string) => {
      window.dispatchEvent(
        new CustomEvent('route-push', {
          detail: {
            nextUrl,
          },
        }),
      );
    };
  • window객체에 route-push 커스텀 이벤트의 리스너 콜백함수를 등록하는 함수.
    리스너 함수는 event객체에서 이벤트 발생 시 저장한 이동 url을 꺼내와서 history.pushState를 실행해 url을 이동 시켜준 후, route함수를 실행시킨다.
     // router.ts
     export const pushRouter = (onRoute: () => void) => {
      window.addEventListener(ROUTE_PUSH_EVENT_NAME, (e: CustomEventType) => {
       const { nextUrl } = e.detail;
       if (nextUrl) {
         history.pushState(null, null, nextUrl);
         onRoute();
       }
     });
    };
  • 현재 페이지에서 pathName을 받아온 후 매칭된 컴포넌트를 생성하는 함수
    // routes.ts
    const route = (target: Element) => {
      const { pathname } = window.location;
      switch (pathname) {
        case '/':
          new Home(target);
          break;
        case '/HexColors':
          new HexColors(target);
          break;
        case '/RandomQuotes':
          new RandomQuotes(target);
          break;
        default:
          console.log('not found page');
      }
    };

2. 처음 app이 실행 될 때 전역 객체에 이벤트를 등록해주기 위해 App컴포넌트에 router함수를 실행시킨다

  // App.ts

  ...
  
  setInitRouter(target: Element) {
    router(target);
    pushRouter(() => {
      router(target);
    });
    replaceRouter(() => {
      router(target);
    });
    popStateRouter(() => {
      router(target);
    });
  }

   mounted() {
    ...
    this.setInitRouter($main);
  }

3. url이동이 필요한 경우 push함수를 불러와 실행시킨다

  handleClickContent(e: Event) {
    console.log('handler');
    const { target } = e;
    if (target instanceof HTMLElement) {
      const { url } = target.dataset;
      push(url);
    }
  }

webpack devServer Cannot GET문제

문제점
devServer로 브라우저 실행 시 라우터로 url을 이동했을 때 Cannot GET문구가 뜨면서 제대로 동작하지 않았다

해결책

// webpack.config.js
module.exports = {
  ...
  output: {
    ...
    publicPath: '/'
  },
  devServer: {
    historyApiFallback: true, // 이걸 추가해줘야 했음
  },
}
profile
#프론트엔드

0개의 댓글