자바스크립트로 투두리스트 (todo-list) 만들기 2편입니다.
완성본과 HTML 과 CSS 는 1편에서 확인해주세요
1편 https://qowbtm45.tistory.com/44
기능 설명 (2편)
1. router 기능 구현
2.카테고리 클릭 시 카테고리에 맞는 주소로 이동하게 하기
라우팅 (routing)에 대해서
- 출발지에서 목적지까지의 경로를 결정하는 기능
- 일반적으로 사용자가 요청한 URL 또는 이벤트를 해석 => 새로운 페이지로 전환하기 위해 데이터를 서버에 요청하고 페이지를 전환하는 일련의 행위
- 애플리케이션의 라우팅 경우에는 사용자가 task 를 수행하기 위해 어떤 화면 (view) 에서 다른 화면으로 화면을 전환하는 내비게이션을 관리하기 위한 기능을 의미함
브라우저가 화면을 전환하는 경우
1. 브라우저의 주소창에 URL 을 입력하면 해당 페이지로 이동
2. 웹 페이지의 링크 (a 태그) 를 클릭하면 해당 페이지로 이동
3. 브라우저의 뒤로가기 또는 앞으로 가기 버튼을 클릭하면 사용자 방문 기록(history) 의 뒤 또는 앞으로 이동
( history 관리를 위해서는 각 페이지는 브라우저의 주소창에서 구별할 수 있는 유일한 URL을 소유해야함 )
Router 기능 구현하기
routes
routes = [];
1. url 과 callback 이 담길 빈 배열 (default)
notFoundCallback ()
notFoundCallback = () => {};
1. 원하는 라우트가 없을 경우 실행하는 콜백함수를 클래스 변수로 추가 (default)
addRoute ()
addRoute(url, callback) {
this.routes.push({
url,
callback,
});
return this;
}
1. 해당되는 url 을 진입했을 때 콜백을 실행함
2. routes 에 url 과 callback 을 넣어줌 (push)
3. 인스턴스 생성 시 체이닝을 사용할 수 있도록 this를 return
인스턴스 (instance)
- 객체 지향 프로그래밍 (OOP) 에서 클래스에 소속된 개별적인 객체
- 하나의 클래스를 사용하여 유사 성질을 가진 수많은 인스턴스를 생성 가능
- 클래스에서 실제 객체를 생성하는 것을 인스턴스화 (instantiation) 라고 함
체이닝 (chaining) or 체이닝 패턴
- 객체에 연쇄적으로 메서드를 호출할 수 있도록 하는 패턴
- 여러가지 동작을 수행할 때, 먼저 수행한 동작의 반환 값을 변수에 할당한 후 다음 작업을 할 필요가 없음
=> 호출을 여러줄에 걸쳐 쪼개지 않아도 된다.
- 메서드에 의미있는 반환 값이 존재하지 않는다면, 현재 작업중인 객체 인스턴스인 this 를 반환
체이닝 (chaining) or 체이닝 패턴의 장점과 단점
- 장점
1. 코드량이 줄어든다 => 코드가 간결해져서 하나의 문장처럼 읽히게 할 수 있음
2. 함수를 쪼개는 방법을 생각하게 된다. ( 유지보수 개선 )
- 단점
1. 디버깅 하기 어렵다 => 코드의 어느 라인에서 에러가 발생했는지 알아내도, 그 라인에서 수행하는 일이 너무 많을 수 있음
checkRoute ()
checkRoute() {
const currentRoute = this.routes.find(
(route) => route.url === window.location.hash
);
if (!currentRoute) {
this.notFoundCallback();
return;
}
currentRoute.callback();
}
1. currentRoute 라는 현재 라우트를 저장할 곳을 만들어준다. (routes array) 에서 찾아야 하는 값
2. 만들어놓은 routes 배열 ( 라우트들이 저장된 곳 )에서 route.url 과 window.location.hash ( 현재 주소 )와 같은 route 를 반환
3. 만약에 currentRoute 가 없다면 ( 저장된 라우트 url 과 현재 주소가 맞는게 없는 경우 ) notFoundCallback() 을 실행
=> notFoundCallback() 은 밑에서
4. 맞는 라우트를 찾으면 , 그 라우트의 callback 을 실행하게 됨
window.location.hash
- 현재 url 의 # 뒤에 있는 string 을 반환해줌
init ()
init() {
window.addEventListener("hashchange", this.checkRoute.bind(this));
if (!window.location.hash) {
window.location.hash = "#/";
}
this.checkRoute();
}
1. 라우트를 초기화해주는 함수
2. hashchange 이벤트로 checkRoute () 를 실행해준다 ( 초기화 되었을 때 )
3. 만약에 현재 주소 값이 없을 경우에는, 기본 값으로 '#/' 을 넣어준다.
setNotFound ()
setNotFound(callback) {
this.notFoundCallback = callback;
return this;
}
1. noFoundCallback 함수에 빈 함수를 추가해줌
2. addRoute() 와 동일하게 체이닝을 사용할 수 있도록 this 를 return 한다.
Router 인스턴스 추가
DOMContentLoaded 이벤트에 Router 인스턴스 추가
document.addEventListener("DOMContentLoaded", () => {
const router = new Router();
...
});
routeCallback
document.addEventListener("DOMContentLoaded", () => {
...
const routeCallback = (status) => () => {
todoList.filterTodo(status);
document.querySelector(
`input[type='radio'][value='${status}']`
).checked = true;
};
});
1. hash 로 받은 ALL/TODO/DONE 을 상태값(status) 를 받음
2. 상태값을 필터링하는 filterTodo에 파라미터로 status 를 전달해줌
3. 콜백이 실행될 때마다 (url 이 바뀔 때마다) 카테고리의 버튼이 활성화된 상태인 input 을 찾음 (각각 실행)
4. routeCallback 에 함수를 넣어버리는 순간, 바로 함수가 실행된다
=> 클로저를 활용해 status를 가진 채로 함수가 함수를 리턴을 하도록 한다
=> routeCallback 에서 url 과 status 를 담은 실행되지 않는 함수가 리턴됨.
클로저(Closure)
- 함수와 함수가 선언된 어휘적 환경의 조합
- "함수"란 반환된 내부함수를 의미함
- 그 함수가 선언될 때의 렉시컬 환경 (Lexical environment) 란 내부 함수가 선언됐을 때의 스코프를 의미함
- 즉 자신이 생성될 때의 환경 (렉시컬 환경 (Lexical environment)) 을 기억하는 함수
클로저를 사용하는 이유
- 전역변수를 줄일 수 있음
=> 함수 하나에 사용하는 전역변수가 필요한 순간이 있음. 그때 유용하게 사용됨
- 코드의 가독성도 좋은 재사용하기 편한 코드를 구현할 수 있음
참고 영상 https://www.youtube.com/watch?v=MbYShFxp-j0
Router 의 메서드에 상태값 전달
document.addEventListener("DOMContentLoaded", () => {
...
router
.addRoute("#/all", routeCallback("ALL"))
.addRoute("#/todo", routeCallback("TODO"))
.addRoute("#/done", routeCallback("DONE"))
.setNotFound(routeCallback("ALL"))
.init();
});
1. router 클래스의 addRoute() 에 카테고리의 hash 값을 정해서 전달
2. callback 에는 위에서 만든 routeCallback 함수를 넣어주도록 함
=> 상태값은 위 코드와 같이 전달
3. setNotFound() 는 위 3개 상태값에 해당되지 않을 때 그냥 ALL 상태값을 갖는 콜백을 실행할 수 있도록 함
4. init () 을 추가해, hashchange 이벤트를 감지할 수 있도록 추가함
todoList 클래스 메서드 수정
onClickRadioBtn ()
onClickRadioBtn(event) {
const { value } = event.target;
// this.filterTodo(value);
window.location.href = `#/${value.toLowerCase()}`;
}
1. filterTodo 에는 status를 전달해주기 때문에, value 를 전달해주는 코드는 없애준다.
=> onClickRadionBtn 클릭 시 기존의 filterTodo() 는 Router 쪽에서 콜백으로 사용됨
2. window.location.href 에 클릭한 카테고리의 값을 템플릿 리터널을 사용해서 소문자로 바꿔주고 #/ 을 붙여준 url 로 이동할 수 있게 한다.
window.location.href
- href 는 location 객체에 속해있는 프로퍼티로 현재 접속중인 페이지 정보를 갖고 있음
- 또한 값을 변경할 수 있는 프로퍼티이기 때문에 다른 페이지로 이동하는데도 사용되고 있음
전체 기능 구현 코드
'Javascript > 응용프로젝트' 카테고리의 다른 글
[3] 자바스크립트로 투두리스트(todo-list) 만들기 + localStorage에 대해서 (0) | 2023.01.09 |
---|---|
[1] 자바스크립트로 투두리스트(todo-list) 만들기 (0) | 2023.01.06 |
자바스크립트로 그림판 만들기 (+ 다운로드 기능) (0) | 2023.01.05 |
자바스크립트로 BMI 계산기 구현하기 (0) | 2023.01.03 |
자바스크립트로 Date-Picker 구현하기 (0) | 2023.01.03 |