Vue와 Vue-router를 이용해 싱글 페이지 앱(SPA)을 만드는 것은 매우 쉽다.
Vue.js를 사용한다면 이미 컴포넌트로 앱을 구성하고 있을 것이고,
Vue-router를 함께 사용하기 위해 추가로 해야 하는 것은
route에 컴포넌트를 매칭한 후, 어떤 주소로 랜더링 할지 알려주는 것 뿐이다.
# with npm
npm install vue-router
# with yarn
yarn add vue-router
모듈 시스템에서 사용하면 Vue.use()
를 통해 명시적으로 라우터를 추가해야한다.
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 폴더 구조
├── router
│ └── index.js
├── components
│ └── Foo.js
│ └── Bar.js
├── App.vue
└── main.js
import vue-router
, Vue.use(VueRouter)
호출, 라우트 정의 및 router 인스턴스 생성
// router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Foo from '../components/Foo.vue';
import Bar from '../components/Bar.vue';
Vue.use(VueRouter);
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
const Router = new VueRouter({
routes: [
routes // `routes: routes`의 줄임
],
});
export default Router;
<router-view> : 페이지 표시 태그, url에 따른 컴포넌트가 화면에 그려지는 영역
<router-link to="경로"> : 컴파일 시, <a>
태그로 변환
to 속성
- 클릭 시 to 속성 값의 경로로 이동
- v-bind
와 함께 사용하면 동적으로 경로를 만들 수 있음
- to="test/path"
처럼 붙이면 현재 url에 이 path가 붙고,to="/test/detail"
처럼 붙이면 default url에 붙음 (대표적)
- styling : router-link-exact-active
등 class를 통해 스타일을 줄 수 있음
<!-- App.vue -->
<template>
<div id="app">
<router-link to="/foo">go Foo</router-link>
<br />
<router-link to="/bar">go Bar</router-link>
<router-view></router-view>
</div>
</template>
루트 인스턴스를 만들고 mount함. router와 router 옵션을 전체 앱에 주입
// main.js
import Vue from 'vue';
import App from './App.vue';
import Router from './router/index';
new Vue({
router: Router,
render: h => h(App),
}).$mount('#app')
this.$route
: 전역 라우트 객체 사용this.$router
는 정확히 router
와 동일하다.
this.$router
를 사용하는 이유는 라우터를 조작해야하는 모든 컴포넌트에서 라우트 객체를 가져올 필요가 없기 때문이다.
<router-link>
는 현재 라우트와 일치할 때 자동으로 .router-link-active
클래스가 추가된다.
주어진 패턴을 가진 라우트를 동일한 컴포넌트에 매핑해야 하는 경우가 자주 존재한다.
const Product = {
template: '<div>Product</div>'
}
const router = new VueRouter({
routes: [
// 동적 세그먼트는 콜론으로 시작
{ path: '/product/:id', component: Product }
]
})
const Product = {
template: '<div>Product {{ $route.params.id }}</div>'
}
동적 세그먼트는 콜론(:)으로 표시된다.
라우트가 일치하면 동적 세그먼트의 값은 모든 컴포넌트에서 this.$route.params
로 표시된다.
그러므로 User의 템플릿을 다음과 같이 갱신하여 현재 Product ID를 표현할 수 있다.
동일한 라우트에 여러 동적 세그먼트를 가질 수 있으며, $route.params
의 해당 필드에 매핑된다.
$route.params
외에도 $route
객체는 $route.query
(URL에 쿼리가 있는 경우), $route.hash
등의 유용한 정보를 제공한다.
매개 변수와 함께 라우트를 사용할 때 주의 해야할 점은 사용자가 /user/foo에서 /user/bar로 이동할 때 동일한 컴포넌트 인스턴스가 재사용된다는 것이다.
두 라우트 모두 동일한 컴포넌트를 렌더링하므로 이전 인스턴스를 삭제 한 다음 새 인스턴스를 만드는 것보다 효율적이지만, 이는 또한 컴포넌트의 라이프 사이클 훅이 호출되지 않음을 의미한다.
즉, 컴포넌트의 라이프 사이클 훅이 호출되지 않기 때문에 params 변경사항에 반응하기 위해서는 watch 옵션으로 $route객체의 수정을 감지해야한다.
const Product = {
template: '...',
watch: {
'$route' (to, from) {
// 라우트 변경에 대한 반응
}
}
}
const Product = {
template: '...',
beforeRouteUpdate (to, from, next) {
// 라우트 변경에 대한 반응
// don't forget to call next()
}
}
동일한 URL이 여러 라우트와 일치하는 경우, 일치하는 우선 순위는 라우트 정의의 순서에 따라 결정된다.
즉, 경로가 더 먼저 정의 될수록 우선 순위가 높아진다.