웹 애플리케이션에서 다른 페이지 간의 전환과 경로를 관리하는 기술
페이지는 1개이지만, 주소에 따라 여러 컴포넌트를 새로 렌더링하여 마치 여러 페이지를 사용하는 것처럼 보이도록 해야함
Home, About 링크에 따라 변경되는 URL과 새로 렌더링되는 화면

1. App.vue 코드 변화
2. router 폴더 신규 생성
3. views 폴더 신규 생성
<a> 태그를 렌더링App.vue<template>
<header>
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</header>
<RouterView />
</template>


index.js
const router = createRouter({
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
...
]
})
App.vue
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
App.vue
<RouterView />
index.js
const router = createRouter({
routes: [
{
path:'/',
name: 'home',
component: HomeView
},
...
]
})
App.vue
<RouterLink to="{ name: 'home' }">Home</RouterLink>
<RouterLink to="{ name: 'about' }">About</RouterLink>
주어진 패턴 경로를 동일한 컴포넌트에 매핑해야 하는 경우 활용
예를 들어 모든 사용자의 ID를 활용하여 프로필 페이지 URL을 설계한다면?
일정한 패턴의 URL 작성을 반복해야 함
views 폴더 내 UserView 컴포넌트 작성
UserView.vue
<template>
<div>
<h1>UserView</h1>
</div>
</template>
UserView 컴포넌트 라우트 등록
index.js
import UserView from '../views/UserView.vue'
const router = createRouter({
routes: [
{
path:'/user/:id',
name: 'user',
component: UserView
},
]
})
UserView 컴포넌트로 이동하기 위한 RouterLink 작성
App.vue
import {ref} from 'vue'
const userId = ref(1)
App.vue
<RouterLink :to="{ name: 'user', params: {'id': userId}">User</RouterLink>
현재 사용자의 id를 출력하기
UserView.vue
<template>
<div>
<h1>UserView</h1>
<h2>{{ $route.params.id }}번 User 페이지</h2>
</div>
</template>

UserView.vue
import { ref } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const userId = ref(route.params.id)
UserView.vue
<template>
<div>
<h1>UserView</h1>
<h2>{{ userId }}번 User 페이지</h2>
</div>
</template>
componenets 폴더에 UserProfile, UserPosts 컴포넌트 작성
UserProfile.vue
<template>
<div>
<h1>UserProfile</h1>
</div>
</template>
UserPosts.vue
<template>
<div>
<h1>UserPosts</h1>
</div>
</template>
index.js에 두 컴포넌트를 import
index.js
import UserProfile from '@/components/UserProfile.vue'
import UserPosts from '@/components/UserPosts.vue'
index.js
{
path: '/user/:id',
name: 'user',
component: UserView,
children: [
// UserProfile은 UserView의 <RouterView> 내부에 렌더링
{ path: 'profile', name: 'user-profile', component: UserProfile },
// UserPosts는 UserView의 <RouterView> 내부에 렌더링
{ path: 'posts', name: 'user-posts', component: UserPosts }
]
}
<a>태그를 만드는 것처럼 프로그래밍으로 네비게이션 관련 작업을 수행할 수 있음| 선언적 표현 | 프로그래밍적 표현 |
|---|---|
<RouterLink :to="..."> | router.push(...) |
UserView.vue
import { useRoute, userRouter } from 'vue-router'
const router = useRouter()
const goHome = function() {
router.push({ name: 'home' })
}
UserView.vue
<button @click="goHome">홈으로!</button>
const goHome = function() {
// router.push({ name: 'home' })
router.replace({ name: 'home' })
}
라우트 전환 전/후 자동으로 실행되는 Hook
작성 위치: index.js
router.beforeEach((to, from) => {
...
return false 또는 return { name: 'About' }
})
index.js
router.beforeEach((to, from) => {
console.log(to)
console.log(from)
})
export default router
to에는 이동할 URL인 user 라우트에 대한 정보가,
from에는 현재 URL인 home 라우트에 대한 정보가 들어있음
LoginView.vue
<template>
<div>
<h1>Login View</h1>
</div>
</template>
index.js
import LoginView from '@/views/LoginView.vue'
{
path: '/login',
name: 'login',
component: LoginView,
},
App.vue
<RouterLink :to="{ name: 'login' }">Login</RouterLink>
어떤 RouterLink를 클릭해도 LoginView 컴포넌트만 볼 수 있음

만약 로그인이 되어있지 않고(1),
이동하는 주소 이름이 login이 아니라면(2),
login 페이지로 redirect
index.js
router.beforeEach((to, from) => {
const inAuthenticated = false
if (!isAuthenticated && to.name !== 'login) {
console.log('로그인이 필요합니다.')
return { name: 'login' }
}
})
작성 위치: index.js의 각 routes
단순히 URL의 매개변수나 쿼리 값이 변경될 때는 실행되지 않고, 다른 URL에서 탐색해올 때만 실행됨
index.js
{
path: '/user/:id',
name: 'user',
component: UserView,
beforeEnter: (to, form) => {
...,
return false
}
},
index.js
{
path: '/user/:id',
component: UserView,
beforeEnter: (to, form) => {
console.log(to)
console.log(from)
}
},

"이미 로그인한 상태라면 LoginView 진입을 막고 HomeView로 이동시키기"
전역 가드 beforeEach 관련 코드는 주석 처리 후 진행
로그인 상태라면 Home View로 이동
로그인한 상태가 아니라면 LoginView로 이동
const isAuthenticated = true
const router = createRouter({
routes: [
{
path: '/login/,
name: 'login',
component: LoginView,
beforeEnter: (to, from) => {
if (isAuthenticated === true) {
console.log('이미 로그인한 상태입니다.')
return { name: 'home' }
}
}
},
...
작성 위치: 각 컴포넌트의
<script>내부
현재 라우트에서 다른 라우트로 이동하기 전에 실행
사용자가 현재 페이지를 떠나는 동작에 대한 로직을 처리
"사용자가 UserView를 떠날 시 팝업 창 출력하기"
UserView.vue
import { onBeforeRouteLeave } from 'vue-router'
onBeforeRouteLeave((to, from) => {
const answer = window.confirm('정말 떠나실 건가요?')
if (answer === false) {
return false
}
})
이미 렌더링된 컴포넌트가 같은 라우트 내에서 업데이트 되기 전에 실행
라우트 업데이트시 추가적인 로직을 처리
"UserView 페이지에서 다른 id를 가진 User의 UserVIew 페이지로 이동하기"
같은 라우트 내에서 업데이트 되는 경우 (/user/1 -> /user/100)
UserView.vue
<button @click="routeUpdate">100번 유저 페이지</button>
UserView.vue
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
const routeUpdate = function () {
router.push({ name: 'user', params: { id: 100} })
}
onBeforeRouteUpdate((to, from) => {
userId.value = to.params.id
})
컴포넌트가 재사용되었기 때문
index.js
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited
component: () => import('@/views/AboutView.vue')
}),
앱을 빌드할 때 처음부터 모든 컴포넌트를 준비하면 컴포넌트의 크기에 따라 페이지 로드 시간이 길어질 수 있기 때문