라우터 (SPA)- vanilaJS 로 만들기

roberto·2022년 6월 18일
0
post-thumbnail

현재는 SPA프레임 워크인 react 를 사용하고있지만 기존에 쉽게 사용하는 기능들을 심도 있게 알아보기 위해
단일 페이지 애플리케이션 (SPA) 의 특징인 라우터에대해 심도있게 알아볼 필요가 생겼다.
평소개발시에는 react-router 로 별어려움 없이 라우트 기능을 사용했었다.
하지만, 정작 라우트 구현방식과 구현에대해선 생각해볼 기회가 없어 vanilJS 로 직접 router를 구현해보았다.

SPA는 기본적으로 웹애플리케이션에 필요한 리소스를 처음 접근시 한번만 다운로드한다 (SPA 가 처음 로딩시 느린이유가 되기도 한다 )

📌라우터 구현 방식

1. Url Hash 방식

2. History Api 방식

history, location 등 HTML5 API를 사용.
HTML5 API: visibilitychange, popstate, beforeunload등 window event를 활용하여 페이지 전환 이벤트 시 핸들러를 등록한다.


1. Url Hash 방식

anchor 태그를 사용한다. (url 정보에 #이 붙는다. )


Hash 방식은 URI의 fragment identifier(#service)의 고유 기능인 앵커(anchor)를 사용.

import { Home, Service, About, NotFound } from './components.js';

const root = document.getElementById('root');

//경로 설정 
const routes = [
  { path: '', component: Home },
  { path: 'service', component: Service },
  { path: 'about', component: About },
];
const render = async () => {
  try {

    const hash = window.location.hash.replace('#', '');
    const component = routes.find(route => route.path === hash)?.component || NotFound;
    root.replaceChildren(await component());
  } catch (err) {
    console.error(err);
  }
};

1. History Api 방식

History Api 들 :

-back(), forward(), go() : 히스토리 스택조작 api
-pushState(), replaceState() : 주소 url 직접 조작하는 함수
-window.onpopstate : 뒤로가기 이벤트시 호출된다


💁‍♂️여기서 잠깐
window.opnpopstate 에대하여

window.onpopstate = (
	function(event){
    	const { state } = event;
    }
);

history API 의 pushstate 와 window 객체의 popstate 이벤트를 이용 ``` history.pushState(state, title[, url]) : 주어진 상태 값을 히스토리 스택에 추가한다
pushState() 함수를 사용하는 것과 window.location = "#hash" 코드를 실행하는 것은 비슷한 동작을 하는 듯하다. 둘 다 새로운 방문 기록을 생성하여 히스토리 스택에 쌓기 때문 ```

구현


router.js

const router = async () => {
    //💁‍♂️이동할 경로 에대한 component 
    const routes = [
        {path: '/', component: Home},
        {path: '/life' , component: Life},
    ];
    //💁‍ url 변경에따른 객체를 만들어준다 (현재페이지 일떄의 isMatch 파라미터 값은 true)
    const pageMatches = router.map(route =>{
        return {
            route,
            isMatch: route.path === location.pathname,
        };
    });
    //💁‍
    let match = pageMatches.find(page => page.isMatch);
    if(match){
        return match.route.component;
    }else{
        new NotFound($('#root'));
    }
};
export default router;

참고


profile
medium 으로 이전했습니다

0개의 댓글