vue.js/vue.js 2

132. 라우터 네비게이션 가드 (to, from, next) | 특정 URL로 접근하기 전 동작을 정의하는 함수 | 로그인 상태에 따른 로고 이동 링크 처리

DEV-Front 2023. 2. 26. 20:27
반응형

https://router.vuejs.org/guide/advanced/navigation-guards.html

 

Vue Router | The official Router for Vue.js

The official Router for Vue.js

router.vuejs.org

라우터 네비게이션 가드는 데이터를 먼저 호출하고 받아왔을때만 이동되게 특정 URL에 들어가는것을 막는것을 구현할수있다.


1. 라우터 네비게이션 가드 기초 코드 (routre/index.js)

- export default new Vuerouter에서 const router로 변경

 

- router.beforeEach 사용 to, form, next 3가지 콜백이 들어온다.
to → 이동하려는 페이지
form → (현재페이지) 어디서부터 왔는지
next → 다음 페이지로 넘어가기 위해 호출하는 API

 

- next() 를 호출해줘야지만 다음 페이지로 이동한다

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

// 1. export default new Vuerouter에서 const router로 변경
const router = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      redirect: '/login',
    },
    {
      path: '/login',
      component: () => import('@/views/LoginPage.vue'),
    },
    {
      path: '/signup',
      component: () => import('@/views/SignupPage.vue'),
    },
    {
      path: '/main',
      component: () => import('@/views/MainPage.vue'),
    },
    {
      path: '/add',
      component: () => import('@/views/PostAddPage.vue'),
    },
    {
      path: '/post/:id',
      component: () => import('@/views/PostEditPage.vue'),
    },
    {
      path: '*',
      component: () => import('@/views/NotFoundPage.vue'),
    },
  ],
});

// 2. router.beforeEach 사용 to, form, next 3가지 콜백이 들어온다.
router.beforeEach((to, from, next) => {  
  console.log(to);
  console.log(from);
  console.log(next);
  // 3. next 를 호출해줘야지만 다음 페이지로 이동한다
  next();
});
export default router;

2. 특정 페이지에 권한 부여 하는법

- store Import

- meta 사용 | 로그인 체크, 로그인 안했으면 전 페이지로 이동하게 구현

-로그인 안했을시 조건 생성 | auth 속성은 임의로 생성한 속성

import Vue from 'vue';
import VueRouter from 'vue-router';
// 1. store Import
import store from '@/store/index';

Vue.use(VueRouter);

const router = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      redirect: '/login',
    },
    {
      path: '/login',
      component: () => import('@/views/LoginPage.vue'),
    },
    {
      path: '/signup',
      component: () => import('@/views/SignupPage.vue'),
    },
    {
      path: '/main',
      component: () => import('@/views/MainPage.vue'),
      // 2. meta 사용 | 로그인 체크, 로그인 안했으면 전 페이지로 이동하게 구현
      meta: { auth: true },
    },
    {
      path: '/add',
      component: () => import('@/views/PostAddPage.vue'),
      meta: { auth: true },
    },
    {
      path: '/post/:id',
      component: () => import('@/views/PostEditPage.vue'),
      meta: { auth: true },
    },
    {
      path: '*',
      component: () => import('@/views/NotFoundPage.vue'),
    },
  ],
});

router.beforeEach((to, from, next) => {
  // 3. 로그인 안했을시 조건 생성 (auth 속성은 강사가 임의로 생성한 속성)
  if (to.meta.auth && !store.getters.isLogin) {    
    console.log('인증이 필요합니다');
    next('/login'); // 로그인 페이지로 이동 
    return;
  }
  next();
});

export default router;

 


3. 로그인 상태에 따른 로고 이동 링크 처리 (AppHeader.vue)

  logoLink() {
      return this.$store.getters.isLogin ? '/main' : '/login';
    },
<template>
  <header>
    <div>
      <!-- 로그인 상태에 따라서 링크 값 달라지게 구현 :to (v-bind로 변경) -->
      <router-link :to="logoLink" class="logo">
        TIL
        <span v-if="isUserLogin">by {{ $store.state.username }}</span>
      </router-link>
    </div>
    <div class="navigations">
      <!-- 1 -->
      <template v-if="isUserLogin">
        <a href="javascript:;" @click="logoutUser" class="logout-button">
          Logout
        </a>
      </template>
      <!-- 2 -->
      <template v-else>
        <router-link to="/login">로그인</router-link>
        <router-link to="/signup">회원가입</router-link>
      </template>
    </div>
  </header>
</template>

<script>
export default {
  computed: {
    isUserLogin() {
      return this.$store.getters.isLogin;
    },
    logoLink() {
      return this.$store.getters.isLogin ? '/main' : '/login';
    },
  },
  methods: {
    logoutUser() {
      this.$store.commit('clearUsername');
      this.$router.push('/login');
    },
  },
};
</script>

<style scoped>
.username {
  color: white;
}
header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
  background-color: #927dfc;
  z-index: 2;
  box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.05);
}
a {
  color: #dedede;
  font-size: 18px;
}
a.logo {
  font-size: 30px;
  font-weight: 900;
  color: white;
}
.logo > span {
  font-size: 14px;
  font-weight: normal;
}
.navigations a {
  margin-left: 10px;
}
.fixed {
  position: fixed;
  top: 0;
  width: 100%;
}
.logout-button {
  font-size: 14px;
}
a.router-link-exact-active {
  color: white;
  font-weight: bold;
}
</style>

 

반응형