일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Medium
- 웹프로그래밍
- CS
- 고득점Kit
- web
- sql
- Level2
- dp
- Doitvue.js입문
- Level3
- typescript
- Level1
- 리액트
- 배열
- 동적계획법
- 프로그래머스
- VUE
- 카카오
- LeetCode
- 백준
- python
- C++
- 자바스크립트
- 리트코드
- javascript
- 프로그래밍
- 파이썬
- OS
- 코테연습
- react
- Today
- Total
[Vue] Router 본문
Router
SPA
하나의 HTML 파일에서 자바스크립트로 어떤 것이 보일지를 컨트롤한다. 페이지 이동이 일어날 때에도 URL이 변경되는 것이 아니라 화면만 바뀌게 되는데 이 경우 현재 페이지의 정보를 알아낼 수 없으므로 문제가 된다. 따라서 URL이 변경될 때 하나의 SPA에서 해당 URL이 나타내는 페이지를 라우팅시켜줘야하고, 이 때문에 라우팅이 필요하다.
vue-router
npm 설치 후 라우터를 설정한다.
//main.js
import { createApp } from 'vue';
import {createRouter, createWebHistory} from 'vue-router';
import App from './App.vue';
import TeamsList from './components/teams/TeamsList.vue';
import UsersList from './components/users/UsersList.vue';
const router = createRouter({
history: createWebHistory(),
routes: [
{path: '/teams', component: TeamsList}, // our-domain.com/teams..
{path: '/users', component: UsersList}, // our-domain.com/teams..
]
});
const app = createApp(App)
app.use(router);
app.mount('#app');
routes에 path와 렌더링할 컴포넌트를 작성한다.
라우터 뷰가 렌더링할 위치는 router-vue로 지정해줄 수 있다.
<template>
<the-navigation @set-page="setActivePage"></the-navigation>
<main>
<router-view></router-view>
</main>
</template>
navigating with router-link
router-link
를 이용해 원하는 path로 이동 시킬 수 있다.
to
속성에 이동하려는 path를 적는다.
<router-link to="/이동하려는 path">text</router-link>
router-link는 결국 a로 렌더링되므로 a 태그로 스타일링할 수 있다.
a {
text-decoration: none;
background: transparent;
border: 1px solid transparent;
cursor: pointer;
color: white;
padding: 0.5rem 1.5rem;
display: inline-block;
}
a:hover,
a:active {
color: #f1a80a;
border-color: #f1a80a;
background-color: #1a037e;
}
Styling Active Links
router-link는 active 되었을 경우 router-link-active
라는 클래스를 가진다. 이를 이용해서 active 되었을 때 스타일링을 할 수 있다.
a:hover,
a:active,
a.router-link-active {
color: #f1a80a;
border-color: #f1a80a;
background-color: #1a037e;
}
router의 linkActiveClass
옵션으로 active될 때 class 명을 커스텀할 수도 있다.
//main.js
const router = createRouter({
history: createWebHistory(),
routes: [
{path: '/teams', component: TeamsList}, // our-domain.com/teams..
{path: '/users', component: UsersList}, // our-domain.com/teams..
],
linkActiveClass: 'active',
});
Programmatic Navigation
import UserItem from './UserItem.vue';
export default {
components: {
UserItem,
},
inject: ['users'],
methods: {
confirmInput() {
// do something
this.$router.push(' /teams');
}
}
};
Passing data with Rotue Params
//main.js
const router = createRouter({
history: createWebHistory(),
routes: [
{path: '/teams', component: TeamsList}, // our-domain.com/teams..
{path: '/users', component: UsersList}, // our-domain.com/teams..
{path: '/teams/:teamId', component: TeamMember}, // our-domain.com/teams..
],
});
this.$route.param
으로 파라미터를 가져올 수 있다.
import UserItem from '../users/UserItem.vue';
export default {
inject: ['users', 'teams'],
components: {
UserItem
},
data() {
return {
teamName: '',
members: [],
};
},
created() {
//this.$route.path // /teams/t1
const teamId = this.$route.params.teamId;
const selectedTeam = this.teams.find(team => team.id === teamId);
const members = selectedTeam.members;
const selectedMembers = [];
for (const member of members) {
const selectedUser = this.users.find(user => user.id === member);
selectedMembers.push(selectedUser);
}
this.members = selectedMembers;
this.teamName = selectedTeam.name;
}
};
Updating Params Data with Watcher
import UserItem from '../users/UserItem.vue';
export default {
inject: ['users', 'teams'],
components: {
UserItem
},
data() {
return {
teamName: '',
members: [],
};
},
methods: {
loadTeamMembers(route) {
const teamId = route.params.teamId;
const selectedTeam = this.teams.find(team => team.id === teamId);
const members = selectedTeam.members;
const selectedMembers = [];
for (const member of members) {
const selectedUser = this.users.find(user => user.id === member);
selectedMembers.push(selectedUser);
}
this.members = selectedMembers;
this.teamName = selectedTeam.name;
},
},
created() {
this.loadTeamMembers(this.$route);
},
watch: {
$route(newRoute) {
this.loadTeamMembers(newRoute);
}
}
};
Passing Params as Props
파라미터를 prop으로 보낼 수도 있다.
//main.js
const router = createRouter({
history: createWebHistory(),
routes: [
{path: '/teams', component: TeamsList}, // our-domain.com/teams..
{path: '/users', component: UsersList}, // our-domain.com/teams..
{path: '/teams/:teamId', component: TeamMember, props: true},
]
});
Redirecting & Catch All routes
redirect
url을 변경한다.
const router = createRouter({
history: createWebHistory(),
routes: [
{path: '/', redirect: '/teams'},
]
})
alias
url를 변경하지 않고 원하는 페이지로 라우팅시킨다.
const router = createRouter({
history: createWebHistory(),
routes: [
// {path: '/', redirect: '/teams'},
{path: '/teams', component: TeamsList, alias:'/'}, // our-domain.com/teams..
]
})
에러 페이지
path 외에 경로로 진입 시에 에러 페이지 컴포넌트를 보여주도록 설정할 수 있다.
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import TeamsList from './components/teams/TeamsList.vue';
import UsersList from './components/users/UsersList.vue';
import TeamMembers from './components/teams/TeamMembers.vue';
import NotFound from './components/nav/NotFound.vue';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/teams' },
{ path: '/teams', component: TeamsList }, // our-domain.com/teams => TeamsList
{ path: '/users', component: UsersList },
{ path: '/teams/:teamId', component: TeamMembers, props: true },
{ path: '/:notFound(.*)', component: NotFound }
],
linkActiveClass: 'active'
});
const app = createApp(App);
app.use(router);
app.mount('#app');
Nested Route
라우터 안에 children
으로 nested Route를 추가할 수 있다.
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/teams' },
{
path: '/teams',
component: TeamsList,
children: [
{ path: ':teamId', component: TeamMembers, props: true }, //teams/:teamId
] }, // our-domain.com/teams => TeamsList
{ path: '/users', component: UsersList },
{ path: '/:notFound(.*)', component: NotFound }
],
linkActiveClass: 'active'
});
children
이 렌더링 되기 위해서는 부모 컴포넌트 내부에 router-view
를 추가해줘야한다. App.vue에서는 루트 path만 표시하기 때문이다.
Navigating with Name
path에 name을 지정해서 이동시에 해당 name을 이용할 수 있다. path가 변경되더라도 name으로 참조하기 때문에 더 편리하다
//main.js
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/teams' },
{
name: 'teams',
path: '/teams',
component: TeamsList,
children: [
{
name: 'team-members',
path: ':teamId',
component: TeamMembers,
props: true
}
, //teams/:teamId
] }, // our-domain.com/teams => TeamsList
{ path: '/users', component: UsersList },
{ path: '/:notFound(.*)', component: NotFound }
],
linkActiveClass: 'active'
});
<template>
<li>
<h3>{{ name }}</h3>
<div class="team-members">{{ memberCount }} Members</div>
<router-link :to="teamMembersLink">View Members</router-link>
</li>
</template>
<script>
export default {
props: ['id', 'name', 'memberCount'],
computed: {
teamMembersLink() {
// return '/teams/' + this.id;
return {name: 'team-members', params: {teamId: this.id}}
}
}
};
</script>
Query Parameter
query 옵션을 이용해 query parameter를 넘길 수 있다.
접근할 때는 this.$query.sort
와 같이 접근한다.
<script>
export default {
props: ['id', 'name', 'memberCount'],
computed: {
teamMembersLink() {
// return '/teams/' + this.id + ?srot=asc;
return {
name: 'team-members',
params: {teamId: this.id},
query:{ sort: 'asc'}
}
}
}
};
</script>
created() {
// this.$route.path // /teams/t1
this.loadTeamMembers(this.teamId);
console.log(this.$route.query)
},
Rendering Multiple Routes
하나의 화면에 서로 다른 루트를 렌더링하고 싶을 경우 해당 path에 component 옵션을 components로 정한 후 default와 다른 component를 설정해준다.
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/teams' },
{
name: 'teams',
path: '/teams',
components: {
default: TeamsList,
footer: TeamsFooter
},
children: [
{
name: 'team-members',
path: ':teamId',
component: TeamMembers,
props: true
}
, //teams/:teamId
] }, // our-domain.com/teams => TeamsList
{
path: '/users',
components: {
default: UsersList,
footer: UsersFooter,
} },
{ path: '/:notFound(.*)', component: NotFound }
],
linkActiveClass: 'active'
});
<template>
<the-navigation></the-navigation>
<main>
<router-view></router-view>
</main>
<footer>
<router-view name="footer"></router-view>
</footer>
</template>
##
Controlling Scroll behavior
scrollBehavior(to, from, savedPosition)
메소드를 이용해 페이지를 이동했을 때 사용자의 스크롤 위치를 컨트롤할 수 있다.
to
from
saved Position : 백 버튼 누르기전에 사용자의 스크롤 위치
객체를 리턴해야하며 해당 객체는 페이지 이동시 어느 스크롤 위치로 이동시킬 건지 정해준다.
scrollBehavior(to, from, savedPosition) {
console.log(to, from, savedPosition)
return {
left: 0,
top: 0,
}
}
savedPosition을 이용하면 뒤로가기 버튼을 눌렀을 때도 스크롤 위치가 변하지 않도록 할 수 있다.
scrollBehavior(to, from, savedPosition) {
console.log(to, from, savedPosition)
if (savedPosition) {
return savedPosition
}
return {
left: 0,
top: 0,
}
}
Navigation Guard
네비게이션 전에 요청을 취소할 수 있다.
next(false)를 실행하면 네비게이션 요청이 취소된다.
beforeEach
router.beforeEach(function(to, from, next) {
console.log('Global beforeEach');
console.log(to, from);
next();
})
강제로 이동할 path를 지정할 수도 있다.
router.beforeEach(function(to, from, next) {
console.log('Global beforeEach');
console.log(to, from);
if (to.name === 'team-members') {
next();
} else {
next({name: 'team-members', params: {teamId: 't2'}})
}
next();
})
로그인 사용자를 처리할 때 유용하게 사용할 수 있다.
path 레벨 과 컴포넌트 레벨에서도 beforeRouteEnter
를 이용하여 처리할 수 있다.
const router = createRouter({
{
path: '/users',
components: {
default: UsersList,
footer: UsersFooter,
},
beforeEnter(to, from, next) {
console.log('users beofreEnter');
console.log(to, from);
next();
}
},
});
<script>
import UserItem from './UserItem.vue';
export default {
components: {
UserItem,
},
inject: ['users'],
methods: {
confirmInput() {
// do something
this.$router.push('/teams');
}
},
beforeRouteEnter(to, from, next) {
console.log('UserList cmp beforeRoueEnter');
console.log(to, from ,next);
next();
}
};
</script>
afterEach
페이지 렌더링을 강제할 수 없지만 유저의 네비게이션 정보를 얻을 수 있다.
router.afterEach((to, from) => {
//seding analytics data
console.log('Global afterEach')
console.log(to, from);
})
beforeRouteLeave
사용자가 페이지를 떠나기 전을 체크하여 특정 로직을 수행하도록 할 수 있다.
beforeRouteLeave(to, from, next) {
console.log('usersList Cmp beforeRouteLeave');
console.log(to, from);
if (this.changesSaved) {
next();
} else {
const userWatnsToLeave = confirm('Are you sure? You got unsvaed changes!');
next(userWatnsToLeave);
}
},
Metadata 이용하기
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', redirect: '/teams' },
{
name: 'teams',
path: '/teams',
meta: { needsAuth: true },
})
router.beforeEach(function(to, from, next) {
console.log('Global beforeEach');
if(to.meata.needsAuth) {
console.log('Needs Auth!')
}
// console.log(to, from);
// if (to.name === 'team-members') {
// next();
// } else {
// next({name: 'team-members', params: {teamId: 't2'}})
// }
next();
})
'Web > Vue' 카테고리의 다른 글
[Vue] Options API => Composition API: Lifecycle (0) | 2022.10.21 |
---|---|
[Vue] Options API => Composition API (0) | 2022.10.21 |
[Vue] Vuex (0) | 2022.09.13 |
[Vue] v-model (0) | 2022.08.11 |
[Vue] 뷰 CLI에서 사용하는 NPM (0) | 2022.08.08 |