프로그래머스 데브 매칭에 참여하기 위해 바닐라 js만으로 코딩연습을 하고 있다. 별도의 라이브러리 없이 해야하기 때문에 개발위해 당연시 세팅했던 라이브러리 없이 코딩을 하니 좀 어려웠던 부분이 많았다. 그 중 라우팅 기능을 구현하는 것이 어려웠다.
React
사용시react-router-dom
을 사용해서 간단히 라우팅 처리를 하여SPA
앱을 구현했는데, 바닐라에서 어떻게 구현했는지 알아보겠다.
<!DOCTYPE html>
<html lang="ko">
<link rel="stylesheet" href="./style.css" />
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="app"></div>
</body>
<script type="module" src="./src/index.js"></script>
</html>
html파일은 위와 같이 간단히 설정했다.
//index.js
import App from "./App.js";
new App({ $target: document.querySelector(".app") });
index.js에 App을 렌더링하는 함수를 설정해 놓았다. 기존의 React앱에서의 동작원리와 비슷하다고 볼 수 있다.
기본적인 폴더구조는 다음과 같다
app.js를 확인해보자
import Header from "./component/Header.js";
import MainPage from "./page/MainPage.js";
import SignupPage from "./page/SignupPage.js";
import { init } from "./route/router.js";
export default function App({ $target }) {
this.route = () => {
const { pathname } = location;
/**html template을 빈 것을 초기화해주기*/
$target.innerHTML = "";
/**header추가하기*/
new Header({ $target }).render();
if (pathname === "/%EC%82%AC%EC%9B%90%20SPA/index.html") {
new MainPage({ $target }).render();
} else if (pathname === "/%EC%82%AC%EC%9B%90%20SPA/index.html/signup") {
new SignupPage({ $target }).render();
}
};
init(this.route);
this.route();
}
기본적인 뼈대 구조를 보면 쉽게 이해할 수 있을 것이다. location.pathname
을 이용해 URL에 따라 경로를 다르게 설정해주는 것이다. pathname의 조건에 따라 page 렌더링을 해주는 것이다. 밑에 있는 init()
함수는 밑에서 알아보자.
import { routeChange } from "../route/router.js";
export default function Header({ $target }) {
const $header = document.createElement("header");
$target.appendChild($header);
this.render = () => {
const template = `<div id="home">Home</div>
<div id="signup" >Signup</div>`;
$header.innerHTML = template;
};
$header.addEventListener("click", ({ target }) => {
const type = target.id;
if (type === "home") {
routeChange("/%EC%82%AC%EC%9B%90%20SPA/index.html");
} else if (type === "signup") {
routeChange("/%EC%82%AC%EC%9B%90%20SPA/index.html/signup");
}
});
}
여기서부터 init()
함수와 routeChange()
함수를 알아보겠다.
const ROUTE_CHANGE_EVENT = "ROUTE_CHANGE";
// 커스텀 이벤트를 통해 ROUTE_CHANGE 이벤트 발생 시 onRouteChange 콜백 함수를 호출하도록 이벤트를 바인딩.
export const init = (onRouteChange) => {
window.addEventListener(ROUTE_CHANGE_EVENT, () => {
onRouteChange();
});
};
// URL을 업데이트하고 커스텀 이벤트를 발생시키는 함수
export const routeChange = (url, params) => {
history.pushState(null, null, url);
window.dispatchEvent(new CustomEvent(ROUTE_CHANGE_EVENT, params));
};
routeChange에 이동하고자 하는 url을 넣으면 history.pushState()
에 전달되고 customEvent를 만들어 window 전달한다.
🖥️ history.pushState()
history.pushState(state, title, url)
기본 문법은 이와 같다.
State : 브라우저 이동 시 넘겨줄 데이터 (popstate 에서 받아서 원하는 처리를 해줄 수 있음)
Title : 변경할 브라우저 제목 (변경 원치 않으면 null)
Url : 변경할 주소
그리고 init을 실행하면 이것이 실행된다. 그래서 아까 app.js를 확인해보면
//app.js
export default function App({$target}){
this.rooute = () =>{
////
}
init(this.route)
this.route();
}
init함수에 this.route를 전달하여 url이 변경될 때마다 this.route()를 실행하여 렌더링이 되어 SPA앱처럼 동작하는 것을 확인 할 수 있다.