티스토리 뷰
Vue-router
예전에는 아래처럼 별도로 설치해서 사용했지만 지금은 vue-cli 에서 아예 설치를 해준다.
터미널에 아래와 같은 구문으로 라우터를 추가
- ( TypeScript 사용자는 vue-router@3.0+와 vue@2.5+를 사용 )
npm install vue-router
설치한 라우터 사용( 라우터를 명시적 추가 및 선언 )
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// 동적 세그먼트는 콜론으로 시작합니다.
{ path: '/user/:id', component: User }
]
})
동적 세그먼트는 콜론 : 으로 표시한다.
라우트가 이리하면 동적 세그먼트의 값은 모든 컴포넌트에서 this.$route.params 로 표신된다.
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
동일한 라우트에 여러 동적 세그먼트를 가질 수 있으며, $route.params의 해당 필드에 매핑된다.
/user/:username --> /user/tom --> { username:'tom'}
$route.params 외에도 $route 객체는 $route.query (URL에 쿼리가 있는 경우), $route.hash 등의 유용한 정보를 제공한다.
아래는 직접 실무에 도입했던 코드 중 vue-router 설정하는 index.ts 이다.
import Vue from 'vue';
import store from '@/store';
import VueRouter, {RawLocation, Route, RouteConfig } from 'vue-router';
// ---------------------- 중략 -------------------------------//
import { LoginRoute } from '@/router/login';
Vue.use( VueRouter );
const routes: Array<RouteConfig>=[
...LoginRoute,
// ---------------------- 중략 -------------------------------//
{
path: '*',
name: 'notfound',
meta: {
layout: 'full'
},
components: { default: ()=>import('@/views/notfound/NotFound')}
}
];
const router=new VueRouter( {
mode: 'history',
base: process.env.VUE_APP_BASE_URL,
routes,
} );
//전역 가드
router.beforeEach( (to, from, next)=>{
if (to.meta !== undefined) {
const token=getToken();
const metaInfo=to.meta;
//로그인 상태 인지 파악
if (metaInfo.auth) {
//우선 token 값이 있는 사용자 인지 파악 ( store 의 isAuth )
if (token) {
// 로그인한 user 정보 및 token 가져오기 값이 false 일때
if (!isUserLoggedIn()) {
//인증 필요하다는 팝업 띄움.
store.commit( `Alert/${ AlertMutationTypes.VALID_AUTH }`, false );
return next( '/login' );
}else{
//화면 권한
if (metaInfo.authName) {
// console.log( to, from );
const findIdx=getAuthority().findIndex( (item: string)=> item === metaInfo.authName );
if (findIdx !== -1) {
return next();
}else{
//접근 권한이 없는 경우 - 접근권한 없다는 팝업 띄움.
store.commit( `Auth/${ PageAuthMutationType.IS_AUTH }`, false );
// 메인으로 돌려보낸다.
return next('/');
}
}else{
return next();
}
}
}else{
console.log( '인증이 필요합니다' );
return next( '/login' );
}
}
}
return next();
} );
export default router;
책이나 기타 인터넷 뒤져보면 라우터 설정하는 부분을 아래처럼 오브젝트 타입으로 모두 나열하여 설정한다.
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
하지만 실무에서는 보통 라우터 설정 페이지가 많기에 카테고리별로 나누어야 한다.
아래 코드에서 ...LoginRoute 라고 전개연산자를 통해 routes 배열에 합치는 것을 볼 수 있다.
라우터 설정하는 페이지들이 많다면 따로 카테고리별로 분리해 두는 것이 관리면에서 좋다.
const routes: Array<RouteConfig>=[
...LoginRoute,
// ---------------------- 중략 -------------------------------//
{
path: '*',
name: 'notfound',
meta: {
layout: 'full'
},
components: { default: ()=>import('@/views/notfound/NotFound')}
}
];
아래는 로그인 설정 라우트 이다.
login.ts
import { RouteURLManage } from '@/router/url';
import { NavigationGuardNext, Route } from 'vue-router';
import { isUserLoggedIn } from '@/core/auth/utils';
export const LoginRoute=[
{
path: RouteURLManage.LOGIN,
name: 'login',
meta: { layout: 'full', renderClass: 'login' },
beforeEnter: (to:Route, from:Route, next:NavigationGuardNext)=>{
//로그인한 user 정보 및 token 가져오기 - 값이 있을 경우 main 으로 보냄.
if (isUserLoggedIn()) {
return next( '/');
}
return next();
},
component: ()=>import('@/views/login/LoginForm'), //로그인 랜딩 페이지
},
];
설정한 부분을 아래와 같이 간략이 설명을 추가해 보았다.
route 코드 설정 설명 :
{
path: //라우터 주소
name: //라우터 name --> vue 클래스 내에서 this.$router.push({name:'adminList'}) 이런식으로 접근할 때 사용. 권장하지 않음.
meta: {
layout: 'side', // 초기 화면 레이아웃 정할 때 쓰인다. 값이 'side' 일 경우 좌측 사이드 메뉴가 노출되게 된다.
renderClass: // FullType.ts 에 정의 되어 있고 class="wrapper"( 페이지 전체를 감싸는 div ) 에 addClass 할 클래스 이름
auth: // 인증 권한이 필요한 화면 -> 하단 beforeEach 전역 가드에서 설정하고 있다.
authName: // 각 화면의 권한 code name 을 지정하고 있다. 전역가드에서 화면에 접근/불가 등의 기준이 된다.
},
components: {
default: ()=>import( /* vue 페이지 컴포넌트 경로 - 해당 라우터에 접근시 동적 로드*/ ),
header:// 상단 header 컴포넌트 지정 - 멤버일 때 header 컴포넌트가 다르게 지정할 수 있다.
}
}
여기서 등장하는 것이 meta 라는 필드이다.
간혹 Route 에 대한 임의의 정보를 첨부하고 싶을 수 있기에 Vue-router 에서 meta 라는 동적 필드를 추가해 두었다고 한다.
이로 인해 meta 속성의 개체를 허용하고 경로 위치 및 탐색 가드 등 액세스할 수 있는 속성을 추가 정의해 둘 수 있겠다.
위의 'route 코드 설정 설명' 중 meta.auth, meta.authName 등은 LoginRoute.ts 에 추가되어 있지 않다.
해당 로그인 라우터는 인증 및 권한이 필요없는 페이지이기에 그렇다.
로그인한 멤버일 경우 페이지 이동시 meta.auth, meta.authName 등이 필요로 하다.
전역 가드 / 라우터 가드 / 컴포넌트 내부가드
전역 가드
router.beforeEach를 사용하여 보호하기 이전에 전역 등록을 할 수 있다.
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
네비게이션이 트리거될 때마다 가드가 작성 순서에 따라 호출되기 전의 모든 경우에 발생한다.
가드는 비동기식으로 실행 될 수 있으며 네비게이션은 모든 훅이 해결되기 전까지 보류 중 으로 간주된다.
모든 가드 기능은 세 가지 전달인자를 받는다.
- to: 라우트: 대상 Route 객체로 이동.
- from: 라우트: 현재 라우트로 오기전 라우트.
- next: 함수: 이 함수는 훅을 해결하기 위해 호출되야 다음 라우트가 있는지 탐색이 된다. 액션은 next에 제공된 전달인자에 달려 있다.
- next(): 파이프라인의 다음 훅으로 이동. 훅이 없는 경우 네비게이션은 승인.
- next(false): 현재 네비게이션을 중단. 브라우저 URL이 변경되면 from경로의 URL로 재설정됩니다.
- next('/') 또는 next({ path: '/' }): 다른 위치로 리디렉션. 현재 네비게이션이 중단되고 새 네비게이션이 시작된다.
- next(error): (2.4.0 이후 추가) next에 전달된 인자가 Error 의 인스턴스이면 탐색이 중단되고 router.onError()를 이용해 등록 된 콜백에 에러가 전달.
주의 : next 함수를 호출하지 않으면 훅이 절대 불러지지 않는다.
아래는 index.ts 에서 전역가드 부분이다.
//전역 가드
router.beforeEach( (to, from, next)=>{
if (to.meta !== undefined) {
const token=getToken();
const metaInfo=to.meta;
//로그인 상태 인지 파악
if (metaInfo.auth) {
//우선 token 값이 있는 사용자 인지 파악 ( store 의 isAuth )
if (token) {
// 로그인한 user 정보 및 token 가져오기 값이 false 일때
if (!isUserLoggedIn()) {
//인증 필요하다는 팝업 띄움.
store.commit( `Alert/${ AlertMutationTypes.VALID_AUTH }`, false );
return next( '/login' );
}else{
//화면 권한
if (metaInfo.authName) {
// console.log( to, from );
const findIdx=getAuthority().findIndex( (item: string)=> item === metaInfo.authName );
if (findIdx !== -1) {
return next();
}else{
//접근 권한이 없는 경우 - 접근권한 없다는 팝업 띄움.
store.commit( `Auth/${ PageAuthMutationType.IS_AUTH }`, false );
// 메인으로 돌려보낸다.
return next('/');
}
}else{
return next();
}
}
}else{
console.log( '인증이 필요합니다' );
return next( '/login' );
}
}
}
return next();
} );
라우터 가드
- 아래 befoeEnter는 각 라우트에 해당하는 개별 라우트 가드이다.
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Home,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
네비게이션이 트리거될 때마다 가드가 작성 순서에 따라 호출되기 전의 모든 경우에 발생한다.
가드는 비동기식으로 실행 될 수 있으며 네비게이션은 모든 훅이 해결되기 전까지 보류 중 으로 진행된다.
모든 가드 기능은 세 가지 전달인자를 받는다.
- to: 라우트: 대상 Route객체로 이동
- from: 라우트: 현재 라우트로 오기전 라우트
- next: 함수: 이 함수는 훅을 해결하기 위해 호출 되어야 한다.
- next(): 파이프라인의 다음 훅으로 이동. 훅이 없는 경우 네비게이션은 승인.
- next(false): 현재 네비게이션을 중단. 브라우저 URL이 변경되면(사용자 또는 뒤로 버튼을 통해 수동으로 변경됨) from경로의 URL로 재설정된다.
- next('/') 또는 next({ path: '/' }): 다른 위치로 리디렉션.
- next(error): (2.4.0 이후 추가) next에 전달된 인자가 Error 의 인스턴스이면 탐색이 중단되고 router.onError()를 이용해 등록 된 콜백에 에러가 전달.
컴포넌트 내부가드
마지막으로 beforeRouteEnter 와 beforeRouteLeave를 사용하여 라우트 컴포넌트(라우터 설정으로 전달되는 컴포넌트) 안에 라우트 네비게이션 가드를 직접 정의 할 수 있다.
- beforeRouteEnter
- beforeRouteUpdate (2.2 버전에 추가)
- beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 이 컴포넌트를 렌더링하는 라우트 앞에 호출됩니다.
// 이 가드가 호출 될 때 아직 생성되지 않았기 때문에
// `this` 컴포넌트 인스턴스에 접근 할 수 없습니다!
},
beforeRouteLeave (to, from, next) {
// 이 컴포넌트를 렌더링하는 라우트가 이전으로 네비게이션 될 때 호출됩니다.
// `this` 컴포넌트 인스턴스에 접근 할 수 있습니다.
}
}
beforeRouteEnter 가드는 네비게이션이 확인전 가드가 호출된다. 컴포넌트가 생성되지 않은 시점이기에 this에 접근하지 못한다.
그러나 콜백을 next에 전달하여 인스턴스에 액세스는 가능하다. 네비게이션이 확인되고 컴포넌트 인스턴스가 콜백에 전달인자로 전달 될 때 콜백이 호출된다.
beforeRouteEnter (to, from, next) {
next(vm => {
// `vm`을 통한 컴포넌트 인스턴스 접근
})
}
beforeRouteLeave 안에서 this에 직접 접근 할 수 있다.
leave 가드는 일반적으로 사용자가 저장하지 않은 편집 내용을 두고 실수로 라우트를 떠나는 것을 방지하는데 사용한다.
탐색은 next(false)를 호출하여 취소할 수 있다.
클래스 컴포넌트 방식에서 컴포넌트 내부 가드
근데 여기서 주의 해야 할 것은 클래스 컴포넌트 방식에서는 Component.registerHooks 에 미리 등록 하고 써야 한다는 것이다.
import { Component, Vue } from 'vue-property-decorator';
// Register the router hooks with their names
Component.registerHooks([
'beforeRouteEnter',
'beforeRouteLeave',
]);
@Component
export default class TestComponent extends Vue{
public beforeRouteEnter(to:Route, from:Route, next:NavigationGuardNext) {
next();
}
public beforeRouteLeave(to:Route, from:Route, next:NavigationGuardNext) {
next();
}
}
'Programming language > vuejs' 카테고리의 다른 글
axios interceptors 를 활용한 vue + ts + jwt ( token/refreshToken )정리 (0) | 2022.05.25 |
---|---|
vue 정리 - login (로그인) part2 (0) | 2022.05.19 |
vue 정리 - login(로그인) part1 (0) | 2022.05.06 |
vue 정리 part1 - vue 설정. (0) | 2022.05.02 |
Vue.js 요약 (0) | 2019.04.04 |
- Total
- Today
- Yesterday
- Intrinsic
- Angular
- 반복문
- icon font
- 태그
- git checkout -b
- Vue3
- Aptana
- JsDoc
- svg 폰트
- for of 구문
- RefreshToken
- IntrinsicElements
- 리프래시토큰
- 자바스크립트
- react
- CSS
- 코도바
- anime.js
- 내장요소
- svg icon font
- 앵귤러
- react-router-dom
- interceptors
- vue-router
- cordova
- React.StrictMode
- 아이콘 폰트 만들기
- git
- svg모션
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |