예전 KDT에서 바닐라 JS로 라우팅하는 법을 배웠는데 MovieApp을 만들면서 적용하게 되었다. 우선 알아야 할 문법은 아래와 같다
보통 우리가 알고 있는 이벤트는 built in event이다. click, input, submit 같은것 말이다. 그러나 우리가 직접 이벤트를 만들고 데이터를 전송할 수 있다.
new CustomEvent와 dispatchEvent를 사용하려면 우선 addEventListener를 이용해서 customEvent에 들어갈 첫번째 인자(이벤트 이름)를 listen한 상태로 만들어야 한다. 일종의 CustomEvent를 받아들일 준비를 하는 과정이다. 그리고 CustomEvent를 만들어서 dispatch하면 CustomEvent가 fired된다!
// create custom events
const catFound = new CustomEvent('animalfound', {
detail: {
name: 'cat',
},
});
const dogFound = new CustomEvent('animalfound', {
detail: {
name: 'dog',
},
});
// listens for the event
window.addEventListener('animalfound', e => console.log(e.detail.name));
// and dispatch the event
window.dispatchEvent(catFound);
window.dispatchEvent(dogFound);
// cat
// dog
또한 버블링도 가능하다. 그럼, 부모에 eventListener를 걸어놓고 자식에서 dispatch 할 수 도 있다.
<form>
<textarea></textarea>
</form>
const form = document.querySelector('form');
const textarea = document.querySelector('textarea');
// Create a new event, allow bubbling, and provide any data you want to pass to the /// "detail" property
const eventAwesome = new CustomEvent('awesome', {
bubbles: true,
detail: { text: () => textarea.value },
});
// The form element listens for the custom "awesome" event and then consoles the output of the passed text() method
form.addEventListener('awesome', e => console.log(e.detail.text()));
// As the user types, the textarea inside the form dispatches/triggers the event to fire, and uses itself as the starting point
textarea.addEventListener('input', function () {
// Create and dispatch/trigger an event on the fly
// Note: Optionally, we've also leveraged the "function expression" (instead of the "arrow function expression") so "this" will represent the element
this.dispatchEvent(
new CustomEvent('awesome', {
bubbles: true,
detail: { text: () => textarea.value },
})
);
});
익명함수를 이용해 this를 사용하여 event가 dispatch되는 시점을 textarea로 설정하였다.
그럼 history api를 배워보도록 하자.
window.history
api를 통해 다음, 이전 페이지로 이동할 수 있다.
// 앞으로 가기
window.history.forward()
// 뒤로가기
window.history.back()
// go를 통해서 앞뒤로 가기(2페이지 이상으로 이동가능함)
window.history.go(-1)
window.history.go(2)
그런데 일반적으로 인터넷에서 무엇을 클릭하면 history가 쌓여서 앞뒤로 가는 버튼이 활성화 되는데 local에서 SPA를 만들면 의도적으로 history에 기록을 쌓아줘야 한다. 그때 사용되는 메소드가 pushState
이다.
그러나 단순히 pushState를 해준다고 해서 뒤로가기를 눌렀을때 페이지가 랜더링 되는 것은 아니다. 그냥 url만 바뀔 뿐이다. 그래서 popstate 이벤트를 통해 페이지를 랜더링 해줘야한다.
popstate는 페이지가 뒤로가거나 앞으로 갔을때 실행되는 이벤트이다.
window.onpopstate = function(event) {
alert(`location: ${document.location}, state: ${JSON.stringify(event.state)}`)
}
history.pushState({page: 1}, "title 1", "?page=1")
history.pushState({page: 2}, "title 2", "?page=2")
history.replaceState({page: 3}, "title 3", "?page=3")
history.back() // alerts "location: http://example.com/example.html?page=1, state: {"page":1}"
history.back() // alerts "location: http://example.com/example.html, state: null"
history.go(2) // alerts "location: http://example.com/example.html?page=3, state: {"page":3}"
popstate에서 event를 통해 pushState할때 넘겨주었던 data(여기선 page) 를 받을 수 있다.
그럼 커스텀 이벤트와 history API를 통해서 라우팅을 해보도록 하겠다. 다음 글에서 계속 됩니다:)