티스토리 뷰
참고 : 프로그래머스 공식 블로그
'2021 Dev-Matching: 웹 프론트엔드 개발자(하반기)' 기출 문제 해설
프로그래머스에서는 지난 2021년 9월 4일 '2021 Dev-Matching: 프론트엔드 개발자(하반기)'의 과제 테스트가 진행되었습니다. 과제 리뷰가 제공되지 않지만, 어떻게 하면 구현을 더 잘할 수 있었을까?
prgms.tistory.com
리액트 라우터 동작처럼 바닐라 JS 에서도 새로고침 없이 부드럽게 넘어가는 SPA를 만드는 법을 공부했다.
0. 페이지 구조
Home 클릭 시 메인화면으로 넘어오고, Sign Up 클릭 시 회원가입 페이지로 넘어간다.
메인화면
회원가입 화면
1. 파일 구조
2. 파일 역할
2-1. Index.js
- Index.html - Index.js 연결
- Index.js 에서 App 컴포넌트를 만듦
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>Main</title>
</head>
<body>
<div class="app"></div>
<script src="./Index.js" type="module"></script>
</body>
</html>
import App from "./App.js"
const $target = document.querySelector('.app');
const $app = new App({$target});
2-2. App.js
import Header from "./Components/Header.js";
import HomePage from "./Page/HomePage.js";
import SignupPage from "./Page/SignupPage.js";
import { init } from "./Route.js";
export default function App({$target}) {
this.route = () => {
const {pathname} = location;
console.log('init');
$target.innerHTML = ``;
const header = new Header({$target})
if (pathname === "/index.html") {
const homePage = new HomePage({$target});
} else if (pathname === "/signup.html") {
const signupPage = new SignupPage({$target});
}
}
init(this.route);
window.addEventListener('popstate', this.route());
this.route();
}
this.route()
this.route = () => {
const {pathname} = location;
console.log('init');
$target.innerHTML = ``;
const header = new Header({$target})
if (pathname === "/index.html") {
const homePage = new HomePage({$target});
} else if (pathname === "/signup.html") {
const signupPage = new SignupPage({$target});
}
}
- #app 내의 innerHTML 을 비워줌으로써 이전 페이지를 지운다.
- location 객체의 pathname 프로퍼티를 가져와 페이지의 url을 체크한다
- 페이지의 이름에 따라 HomePage / SignupPage 컴포넌트를 렌더링한다
2-3 Header.js
import { routeChange } from "../Route.js";
export default function Header({$target}) {
this.$element = document.createElement('header');
this.$element.className = "header";
$target.appendChild(this.$element);
this.render = () => {
this.$element.innerHTML = `
<div class="left_bar">
Home
</div>
<div class="right_bar">
Sign Up
</div>
`
}
this.$element.addEventListener('click', (e) => {
const $div = e.target.closest('div');
if($div.className === "left_bar") {
console.log('move to main page');
routeChange("/index.html");
} else if ($div.className === "right_bar") {
console.log('move to sign up page');
routeChange("/signup.html");
}
})
this.render();
}
Header의 eventListener
this.$element.addEventListener('click', (e) => {
const $div = e.target.closest('div');
if($div.className === "left_bar") {
console.log('move to main page');
routeChange("/index.html");
} else if ($div.className === "right_bar") {
console.log('move to sign up page');
routeChange("/signup.html");
}
})
- click 이벤트 시 클래스명에 따라 다른 url을 넘겨준다.
- routeChange는 Router.js의 url 변경 메소드이다.
2-4 Route.js
const ROUTER_CHANGE_EVENT = 'ROUTER_CHANGE';
export const init = (routerCallBack) => {
window.addEventListener(ROUTER_CHANGE_EVENT, () => {routerCallBack()});
}
export const routeChange = (url, params) => {
history.pushState(null, null, url);
window.dispatchEvent(new CustomEvent(ROUTER_CHANGE_EVENT), params);
}
history.pushState
- 페이지의 이동없이 주소창의 주소를 바꿔준다.
- 브라우저의 세션 스택에 상태를 추가한다.
window.dispatchEvent
- ROUTER_CHANGE_EVENT 이벤트를 새로 커스텀해준다.
- window.dispatchEvent를 통해 새로 커스텀한 이벤트를 실행시켜준다.
init
- addEventListener를 통해 routeChange 메소드에서 ROUTER_CHANGE_EVENT를 실행시킨 것을 감지한다.
- 이때 매개변수로 받은 콜백함수를 실행시키는데, 여기선 App.js의 this.route()를 연결해준다.
App.js
// 생략
import { init } from "./Route.js";
export default function App({$target}) {
// 생략
init(this.route);
}
따라서
1. Header 요소 클릭 시
2. routerChange 메소드에서 url변경, ROUTE_CHANGE_EVENT 이벤트 (강제)실행
3. init 함수에서 이벤트 감지후 this.route() 실행
4. this.route는 현 페이지의 주소에 따라 다시 렌더링
2-5 App.js 의 popState
https://developer.mozilla.org/ko/docs/Web/API/Window/popstate_event
popstate - Web API | MDN
Window 인터페이스의 popstate 이벤트는 사용자의 세션 기록 탐색으로 인해 현재 활성화된 기록 항목이 바뀔 때 발생합니다. 만약 활성화된 엔트리가 history.pushState() 메서드나 history.replaceState() 메서
developer.mozilla.org
뒤로가기 이벤트 처리를 위해 작성해주었다.
세션기록 항목이 변경될 때 해당 이벤트가 발생된다.
import Header from "./Components/Header.js";
import HomePage from "./Page/HomePage.js";
import SignupPage from "./Page/SignupPage.js";
import { init } from "./Route.js";
export default function App({$target}) {
// 생략
window.addEventListener('popstate', this.route());
this.route();
}
'Web > FrontEnd' 카테고리의 다른 글
[CSS] 다운로드 한 폰트 적용 (0) | 2023.01.27 |
---|---|
[메모] 자바스크립트 코드 컨벤션 (0) | 2022.10.25 |
[JS, 프로젝트] 프로젝트 - API 호출 연습 (0) | 2022.04.12 |