제 2장 SPA로 작동하도록 라우터 개선
업데이트: Link
2. SPA로 작동하도록 라우터 개선
나만의 라우터 만들기 시리즈 의 4부 중 2부
알렉스 조버 모랄레스씀
이 시점에서 라우터는 window.location
강제 리로드를 수행하는 새 경로를 직접 할당하기 때문에 단일 페이지 앱(SPA) 라우터로 작동하지 않습니다.
라우터를 SPA 라우터로 사용하도록 조정하기 위해 무엇을 해야 하는지 봅시다.
해시 및 HTML5 기록
강제 리로드를 처리하기 위해 모드 라고 하는 두 가지 대안이 있습니다.
- hash : 해시를 사용 하여 SPA와 다른 경로인 프래그먼트 식별자 를 정의 합니다.
이렇게 하면 프런트 엔드 라우팅이#
마크 에서 시작됩니다.
이것이 전통적인 방법입니다. 예:https://example.io/#/home
- HTML 5 history : HTML 5 history API 를 사용하는 것이 현대적인 방법입니다.
이 모드에는 해시가 필요하지 않습니다.
이 기사에서는 HTML 5 history 모드 를 사용하고 history API 를 사용하는 방법을 살펴보겠습니다. 그러나 해시 모드를 사용하려면 약간의 변경이 필요합니다.
히스토리 모듈 구현
History API에는 window.location
할당 대신 사용할 수 있는 pushState
메서드가 있습니다.
이 pushState
방법은 window.location
할당과 달리 강제 리로드를 수행하지 않으므로 사용하기 적합합니다.
그에 따라 App.vue 에서 goTo
메서드를 업데이트할 수 있습니다.
// App.vue
goTo(route) {
history.pushState(null, null, route)
}
호출에서 처음 두 개의 매개변수(state
및 title
)를 생략할 수 있습니다.
세 번째 매개변수로 수신된 route
에 관심을 주세요.
그러나 여전히 문제가 있습니다. pushState
를 사용하여 경로를 설정하더라도 Router.vue 에서 구성 요소를 업데이트하기 위해 경로 변수 current
가 변경되었음을 알아야 합니다.
이미 History API에 익숙 하다면 onpopstate 이벤트를 사용할 수 있다고 생각할 수도 있지만 자세히 읽어보면 pushState
가 호출 될 때 이벤트가 트리거되지 않는다는 것을 알 수 있습니다.
우리는 여전히 사용자가 뒤로 및 앞으로 브라우저 버튼을 눌렀을 때 그 변화에 반응 할 필요가 있지만 충분하지 않습니다.
이를 해결하기 위해 변경 사항을 수신하고 대신 호출 할 수 있는 기록 래퍼를 만들 수 있습니다.
history.js
파일을 만들고 push
메서드를 래핑하여 시작하겠습니다.
// history.js
export const push = route => {
window.history.pushState(null, null, route);
}
히스토리를 청취 가능하게 만들려면 외부 모듈이 변경 사항을 알리는 데 사용할 listen
콜백 함수를 listeners
변수에 저장하는 메서드를 구현해야 합니다 .
// history.js
const listeners = [];
export const push = route => {
window.history.pushState(null, null, route);
};
export const listen = fn => {
listeners.push(fn);
};
마지막으로 push
메서드는 실제로 리스너를 반복하여 알림을 보내고 경로를 전달하는 콜백 함수를 호출해야 합니다.
이전 경로와 두 번째 인수를 전달할 수 있습니다.
push(route) {
const previousRoute = window.location.pathname;
window.history.pushState(null, null, route);
listeners.forEach(listener => listener(route, previousRoute));
}
외부 모듈에 알리기 위해 리스너를 사용하는 이러한 방식이 친숙해 보인다면,
다른 구성 요소가 변경 사항을 수신할 수 있는 구독 모델을 제공하는 구조를 제공하는 패턴인 Observer Pattern
을 history.js
가 구현 하기 때문 입니다.
최종 코드는 다음과 같습니다.
// history.js
const listeners = [];
export const push = route => {
const previousRoute = window.location.pathname;
window.history.pushState(null, null, route);
listeners.forEach(listener => listener(route, previousRoute));
};
export const listen = fn => {
listeners.push(fn);
};
history.js
모듈도 NPM에 게시 된 외부 패키지로 사용할 수 있습니다.
사실 React Router 팀이 React Router
를 위해 생성한 기존 history npm 패키지가 있지만,
독립적인 모듈이고 API가 거의 동일하기 때문에 이 경우 완벽하게 사용할 수 있습니다.
히스토리 모듈 사용
이제 history.js
가 구현되었습니다. pushState
호출을 대신하여 App.vue 에서 사용하겠습니다.
// App.vue
import Router from "./Router";
import { push } from "./history";
export default {
components: {
Router
},
methods: {
goTo(route) {
push(route);
}
}
};
여전히 AppRouter.vue 구성 요소가 URL 변경 사항을 인식하도록 해야 하며 이제 history
모듈의 listen
메서드를 사용할 수 있습니다.
리스너를 한 번만 설정하면 되므로 Vue.js 구성 요소의 created
후크가 완벽한 위치입니다.
// AppRouter.vue
import { listen } from "./history";
// ...
export default {
created() {
listen((route, previousRoute) => {
this.current = route
});
},
// ...
}
listen
명령문에 전달된 함수는 history
의 리스너에 추가된 다음 나중에 호출될 때 push
가 호출됩니다.
이제 Home
및 Articles
버튼을 클릭 하면 작동합니다.
그러나 당신은 브라우저의 뒤로 및 앞으로의 버튼을 클릭하면 여전히 작동하지 않습니다.
이전에 언급했듯이 이를 위해 popstate
이벤트를 사용해야 하므로 라우터의 created
후크에 추가하고 다음과 같이 마무리합니다.
created() {
listen((route, previousRoute) => {
this.current = route
});
window.addEventListener(
"popstate",
event => (this.current = window.location.pathname)
);
}
마지막으로 다시 시도하면 모든 경우에 완벽하게 작동하는 간단한 라우터입니다. 여기에서 더 많은 기능을 추가할 수 있습니다. 후크와 가드를 추가하는 것은 어떻습니까?
여기 에서 이 기사 의 코드와 데모 를 찾아 직접 사용해 보세요!
댓글남기기