바닐라 자바스크립트를 이용하여 SPA를 위한 간단한 Router를 만들어보고, 관련 개념을 정리하자.
데모페이지와 코드샌드박스 소스코드 주소는 아래와 같다.
html은 다음과 같다. 앵커태그들을 만들고 변경된 html이 주입될 div를 만든다.
// index.html
<!DOCTYPE html>
<html>
<head>
<title>SPA Router - Vanila JavaScript</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="root">
<nav>
<a href="/" id="homeRoute">Home</a>
<a href="/about" id="aboutRoute">About</a>
<a href="/blog" id="blogRoute">Blog</a>
</nav>
<div id="contents"></div>
</div>
<script src="router.js"></script>
</body>
</html>
js는 다음과 같다.
routes
객체를 만든다. getRouteHtml
함수를 만들었고 이 함수는 fetch
를 통해 받은 response의 text()
를 DOM에 삽입한다.handleRoute
함수는 앵커태그 클릭 시 호출된다. 앵커의 href
값을 history.pushState
메서드의 세 번째 인수(url)에 전달하여 브라우저의 URL을 업데이트한다.// route.js
const routes = {
404: "/pages/404.html",
"/": "/pages/index.html",
"/about": "/pages/about.html",
"/blog": "/pages/blog.html",
};
const getRouteHtml = async () => {
const path = window.location.pathname;
const route = routes[path] || routes[404];
const $contents = document.getElementById("contents");
await fetch(route)
.then(response => {
return response.text();
})
.then(text => {
$contents.innerHTML = text;
});
};
const handleRoute = event => {
event = event || window.event;
event.preventDefault(); // anchor 태그의 기본동작인 링크 대상으로 이동하는 행동을 방지한다.
window.history.pushState({}, "", event.target.href);
getRouteHtml();
};
window.onpopstate = getRouteHtml;
getRouteHtml();
document.getElementById("homeRoute").addEventListener("click", handleRoute);
document.getElementById("aboutRoute").addEventListener("click", handleRoute);
document.getElementById("blogRoute").addEventListener("click", handleRoute);
handleLocation 함수 내에서 route를 fetch하여 받은 data는 프로미스이고 콘솔로 찍으면 아래와 같다.
Body 믹스인은 Request나 Response (en-US)에 구현되어, 콘텐츠를 추출하기 위해 아래의 메서드가 정의되어 있다. 이러한 메서드들은 전부 최종적으로 요청으로 반환된 값을 내장하고 있는 promise를 반환한다.
String
으로 Resolve되는 Promise를 반환한다(UTF-8로 디코딩됨).Window.location 프로퍼티에 접근하면 읽기 전용인 Location 객체
를 얻어올 수 있다. 이는 현재 도큐먼트의 로케이션에 대한 정보를 담고 있다.
윈도우 URL이 바뀔 때마다, window.location을 콘솔로 찍으면 아래와 같은 객체를 확인할 수 있다.
Location 인터페이스는 객체가 연결된 장소(URL)를 표현한다. Location 인터페이스에 변경을 가하면 연결된 객체에도 반영되는데, Document와 Window 인터페이스가 이런 Location을 가지고 있다. 각각 Document.location과 Window.location으로 접근할 수 있다.
location.pathname
은 '/' 문자 뒤 URL의 경로를 값으로 하는 DOMString이다.
History 인터페이스는 브라우저의 세션 기록
, 즉 현재 페이지를 불러온 탭 또는 프레임의 방문 기록을 조작할 수 있는 방법을 제공한다.
메서드로 back()
, forward()
, go()
, pushState()
, replaceState()
가 있다.
history.pushState()
는 브라우저의 세션 기록 스택에 상태를 추가한다.history.pushState(state, title[, url]);
매개변수
1. state
: 새로운 세션 기록 항목에 연결할 상태 객체. 사용자가 새로운 상태로 이동할 때마다 popstate 이벤트가 발생하는데, 이 때 이벤트 객체의 state 속성에 해당 상태의 복제본이 담겨 있다.
2. title
: (현재 대부분의 브라우저가 무시) 그냥 빈 문자열 지정
3. url
: 새로운 세션 기록 항목의 URL. 상대 URL을 지정할 수 있으며, 이 땐 현재 URL을 기준으로 사용합니다.
popstate 이벤트는 history.pushState() 또는 history.replaceState()를 통해 발생하는 것이 아니라, 같은 document에서 두 히스토리 엔트리 간의 이동
이 있을 때만 발생한다.
만약 활성화된 엔트리
가 history.pushState() 메서드나 history.replaceState() 메서드에 의해 생성되면, popstate 이벤트의 state 속성
은 히스토리 엔트리 state 객체
의 복사본을 갖게 된다.
안녕하세요~ 각 pages의 html에서만 동작할 수 있도록 자바스크립트를 연동하려면 어떻게 해야되는 지 문의드려도 될까요? 자바스크립트를 root의 index.html에 넣어줘야 동작이 되더라고요.