본문 바로가기
Vue

[Vue] vue-router 사용법

by 메이플 🍁 2022. 8. 12.

vue-router 사용법

https://router.vuejs.org/guide/

 

Getting Started | Vue Router

Getting Started Creating a Single-page Application with Vue + Vue Router feels natural: with Vue.js, we are already composing our application with components. When adding Vue Router to the mix, all we need to do is map our components to the routes and let

router.vuejs.org

1. router를 일반 의존성 패키지로 설치

npm install vue-router

 

2. routes 폴더 안에 index.js 파일 생성 후 createRouter 함수로 라우터 등록해주기

index.js

index.js 라우터의 페이지 정보를 가지고 있는 파일이다.

import { createRouter } from 'vue-router'

export default createRouter({ 옵션 })

 

3. main.js에 라우터 등록하기

index.js에서 export default(기본 내보내기)로 createRouter 함수의 결과가 리턴된다

리턴된 결과를 main.js에 플러그인처럼 등록해서 사용해준다

플러그인에 등록하였으므로 this.$router로 라우터에 언제든지 접근이 가능해졌다

main.js

import { createApp } from 'vue'
import router from './routes'
import App from './App.vue'

createApp(App)
  .use(router)
  .mount('#app')

 

4. history 또는 hash 모드 중 하나 선택 후 옵션에 등록해주기

hash 모드

해시 기호를 기준으로 주소가 변경된다

https://google.com/#/login

해시 기호가 없는 history 모드가 더 선호된다

import { createRouter, createWebHashHistory } from 'vue-router'

export default createRouter({
  history: createWebHashHistory
})

history 모드

해시 기호가 없는 주소를 말한다

https://google.com/login

개발시에는 문제 없이 작동하지만 배포할시 서버 세팅이 필요하다

import { createRouter, createWebHistory } from 'vue-router'

export default createRouter({
  history: createWebHistory()
})

 

5. 라우터가 변경될때마다 스크롤이 자동으로 top: 0가 되게 설정해주기

index.js

import { createRouter, createWebHashHistory } from 'vue-router'

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 })
})

 

6. 컴포넌트별로 라우터 등록해주기

기본문법

routes: [
  {
    path: '도메인을 제외한 url'
    component: 해당 path에 연결할 component
  }
]

index.js

routes 폴더 안에 만들어준 컴포넌트 Home, About을 라우터에 등록해주기

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/about',
      component: About,
    }
  ]
})

 

7. 라우터에 등록해준 컴포넌트를 HTML에 출력해준다

 App.jsx

index.js에 등록한 컴포넌트가 브라우저 주소에 맞게 출력된다.

<template>
  <RouterView />
</template>

 

8. 동적 라우팅 설정해주기

동적 라우팅 (Dynamic Routing)이란?

페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야할 때도 있다. 이때 라우터의 경로에 유동적인 값인 URL 파라미터나 쿼리를 넣어서 특정 페이지로 이동하는데 이것을 동적 라우팅이라고 한다.

routes: [
  {
    path: '/url/:동적파라미터',
    component: 컴포넌트이름,
  }
]

index.js

앞으로 movie/ 주소 뒤에 오는 id값은 this.$route.params.id로 접근할 수 있다.

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
    }
  ]
})

 

9. 중첩 라우팅(Nested Routes) 구현해주기

부모 컴포넌트의 path는 domain을 포함한 절대경로(/url)로 표시하고 자식 컴포넌트의 path는 부모 url 뒤에 사용할 url만 상대경로로 표시해준다(url) 

routes: [
  {
    path: '/url',
    component: 컴포넌트이름,
    children: [
      {
        path: '부모 url 뒤에 사용할 url',
        component: 컴포넌트이름,
      }
    ]
  }
]

index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
      children: [
        {
          // domain/about/name
          path: 'name',
          component: AboutName,
        }
      ]
    }
  ]
})

About.vue

<template>
  <h1>About</h1>
  <RouterLink to="/about/name">
    Name
  </RouterLink>
  <!-- RouterView에는 About 컴포넌트의 children으로 동록된 컴포넌트가 표시된다 -->
  <RouterView />
</template>

 

10. Not Found 페이지 구현해주기

index.js

NotFound 컴포넌트는 배열의 가장 마지막에 위치시켜야 등록된 다른 컴포넌트가 주소에 맞게 렌더링 된다

정규표현식으로 위에서 등록한 path 이외의 모든 url이 로드되면 NotFound 컴포넌트가 렌더링 된다

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';
import NotFound from './NotFound.vue'

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
    },
    {
      path: '/:notFound(.*)',
      component: NotFound
    }
  ]
})

 

11. 컴포넌트에 이름 속성 등록하기

index.js

앞으로 Home 컴포넌트는 this.$router.push({ name: 'mainpage' })로 접근할 수 있다.

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';
import NotFound from './NotFound.vue'

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      name: 'mainpage',
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
    },
    {
      path: '/:notFound(.*)',
      component: NotFound
    }
  ]
})

 

12. 컴포넌트에 redirect 속성 등록하기

index.js

특정 페이지가 보수중일때 임시적으로 다른 페이지 경로로 연결해주는 기능 사용하고 싶을때 redirect 속성을 사용한다. 아래의 코드에서 About 컴포넌트에 redirect 속성을 설정했기 때문에 사용자가 /about 주소로 이동하려고 하면 / 주소로 redirect 된다.

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';
import NotFound from './NotFound.vue'

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      name: 'mainpage',
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
      redirect: '/'
    },
    {
      path: '/:notFound(.*)',
      component: NotFound
    }
  ]
})

 

13. 컴포넌트에 meta 속성 등록하기

메타정보란 페이지에 대한 정보를 의미한다. 아래 About 컴포넌트에 등록한 met 정보는 앞으로 $route.meta.메타이름으로 접근할 수 있다.

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from './Home';
import About from './About';
import Movie from './Movie';
import NotFound from './NotFound.vue'

export default createRouter({
  history: createWebHashHistory,
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      name: 'mainpage',
      path: '/',
      component: Home,
    },
    {
      path: '/movie/:id',
      component: Movie,
    },
    {
      path: '/about',
      component: About,
      meta: { auth: true }
    },
    {
      path: '/:notFound(.*)',
      component: NotFound
    }
  ]
})

 

14. TheHeader 컴포넌트에 페이지를 이동할 수 있는 nav 생성하기

기본구조

<RouterLink :to="도메인 제외한 url">메뉴이름</RouterLink>

TheHeader.vue

routes 폴더가 아닌 components 폴더 안에 TheHeader라는 컴포넌트를 생성한 후 nav를 만들어준다. 이때 RouterLink를 하나씩 만들기보다 데이터로 만든 후 v-for로 한번에 만들어준다.

<template>
  <header>
    <div class="nav nav-pills">
      <div
        v-for="nav in navigations"
        :key="nav.name"
        class="nav-item">
        <RouterLink
          :to="nav.path"
          class="nav-link">
          {{ nav.name }}
        </RouterLink>
      </div>
    </div>
  </header>
</template>

<script>
export default {
  data() {
    return {
      navigations: [
        {
          name: 'Home',
          path: '/'
        },
        {
          name: 'Movie',
          path: '/movie',
        },
        {
          name: 'About',
          path: '/about'
        },
      ]
    }
  }
}
</script>

 

15. 특정 컴포넌트에서만 Header 보여주기 (Named Views)

index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import TheHeader from '~/components/TheHeader.vue'
import Home from './Home.vue'

export default createRouter({
  history: createWebHashHistory(),
  scrollBehavior: () => ({ top: 0 }),
  routes: [
    {
      path: '/',
      // component를 components로 변경
      components: {
        // Home.vue 컴포넌트에서만 TheHeader.vue 컴포넌트 보여주는 작업
        // 순서 관계 없음 (객체 데이터는 키와 밸류의 모음집일뿐 순서가 없다)
        TheHeader, // 'TheHeader': TheHeader,
        default: Home
      }
    }, 
  ]
})

App.js

이름이 없는 RouterView 컴포넌트는 default로 설정한 컴포넌트를 매칭시킨다.

<template>
  <!-- Home 컴포넌트에서만 TheHeader 컴포넌트를 보여주는 작업 -->
  <RouterView name="TheHeader" />
  <!-- 이름이 없는 RouterView 컴포넌트는 default로 설정한 컴포넌트를 매칭 -->
  <RouterView />
</template>

 

16. active한 nav에 클래스 이름 새로 부여하기

RouterLink에서 active한 nav는 라우터에서 자동으로 클래스 이름으로 router-link-active를 붙여준다. 해당 클래스 이름이 너무 길기때문에 다른 클래스이름을 부여해준다.

기본구조

active한 nav에 새로 부여할 클래스이름을 active-class 안에 넣어준다. 클래스 이름으로 보통 active를 많이 사용한다.

<RouterLink :to="도메인 제외한 url" active-class="새로 부여할 클래스 이름">메뉴이름</RouterLink>

TheHeader.vue

<template>
  <header>
    <div class="nav nav-pills">
      <div
        v-for="nav in navigations"
        :key="nav.name"
        class="nav-item">
        <RouterLink
          :to="nav.path"
          active-class="active"
          class="nav-link">
          {{ nav.name }}
        </RouterLink>
      </div>
    </div>
  </header>
</template>

<script>
export default {
  data() {
    return {
      navigations: [
        {
          name: 'Home',
          path: '/'
        },
        {
          name: 'Movie',
          path: '/movie',
        },
        {
          name: 'About',
          path: '/about'
        },
      ]
    }
  }
}
</script>

 

17. navigation guards (Global Before Guards)

navigation guards란?

모든 페이지에 접속하기 전 또는 기존 페이지에서 다른 페이지로 이동할때와 같은 특정 상황을 navigation guards를 통해서 제어할 수 있다. 

Global Before Guards

모든 페이지에 접속하기 전에 상황을 제어하는 것

페이지 접속전 권한 검사 후 통과시키는 역할

권한 검사시 meta 정보를 활용해 통과 여부를 결정한다

라우터 가드 === 검문소

로그인 여부를 확인해서 로그인했을때만 접속이 가능한 페이지를 걸러내는 용도로 주로 사용한다

기본 문법

return true가 있어야 페이지로 넘어갈 수 있다.

import router from './index.js'

// 페이지에 접근하기 직전에 실행되는 함수
router.beforeEach((to, from, next) => {
  // ...
  return true
})

index.js

About 컴포넌트는 meta 정보로 { auto: true } 객체를 가지고 있다.

routes: [
  {
    path: '/about',
    component: About,
    meta: { auth: true }
  }
]

guards.js

routes 폴더 안에 guards.js 파일을 생성한다. beforeEach에 파라미터로 가져온 to는 페이지에 대한 정보를 가진 객체 데이터로 this.$route와 같은 객체를 가진다. About 페이지에만  meta 정보로 { auto: true } 객체를 가지고 있으므로 사용자가 About 페이지에 접속할때만 아래의 콘솔창이 true값을 리턴한다. 로그인 했을때만 접근할 수 있는 페이지를 지정할때 유용하게 사용할 수 있다.

import router from './index.js'

router.beforeEach((to) => {
  console.log(to.meta.auth)
  return true
})

main.js

import 키워드로 guards.js 파일을 연결만 해주면 guards.js 파일 안에 있는 코드가 main.js에 있는 것과 같다

import { createApp } from 'vue'
import router from './routes'
import '~/routes/guards'
import App from './App.vue'

createApp(App)
  .use(router)
  .mount('#app')

guards.js

  1. 로그인한 상태를 만들어주기 위해 웹브라우저 Application에 currentUser의 값으로 { "name": "maple" }를 등록한다
  2. 로그인한 사용자만 들어갈 수 있는 About 컴포넌트에 접속한다
  3. to.meta.auth값으로 true를 가진 About 컴포넌트만 코드가 실행된다 (다른 컴포넌트로 접속하면 guards.js 코드가 실행되지 않음)
  4. currentUser 객체에 있는 값 name을 구조분해할당을 하며 값을 꺼내준다
  5. name의 값이 있으면 (로그인이 된 상태면) true가 리턴되고 About 페이지에 접속이 가능해진다
  6. name의 값이 없으면 (로그인이 안된 상태면) '/'가 리턴되고 Home 페이지로 튕겨져 나간다
import router from './index.js'

router.beforeEach(to => {
  if(to.meta.auth) {
    const { name } = JSON.parse(localStorage.getItem('currentUser') || '{}')
    if(name) {
      return true
    } else {
      return '/'
    }
  }
  return true
})

 


 

라우터에서는 전역적으로 사용할 수 있는 두개의 컴포넌트를 제공한다

1. RouterView

바뀐 페이지가 어느 영역에 렌더링이 될것인지에 대한 영역을 지정해주는 컴포넌트

<RouterView />

2. RouterLink

페이지 이동시 사용하는 HTML의 a 태그 대신 사용할 수 있는 컴포넌트

<RouterLink :to="도메인 제외한 url" active-class="새로 부여할 클래스 이름">메뉴이름</RouterLink>

 

라우터에서는 달러사인($) 기호를 시작으로 하는 두개의 객체를 제공한다

1. $router

$router는 페이지 이동을 명령하는 함수가 들어 있는객체

$router.push()

일반적으로 페이지를 이동할때는 RouterLink라는 컴포넌트를 사용한다. 자바스크립트 내부에서 페이지 이동을 해주는 코드를 작성하고 싶을때는 RouterLink 컴포넌트가 아닌 $router 객체에 있는 push라는 메서드를 사용한다.

주소

$router.push(‘주소’)
this.$router.push(‘/mainpage’)
this.$router.push(‘/s=frozen&page=1’)

name 속성

$router.push({ name: '이름' })
this.$router.push({
  name: 'mainpage'
})

query 속성

this.$router.push({ query: { 속성 } })
this.$router.push({ 
  query: {
    s: ‘frozen’
    page: ‘1’
  }
})

$router.go()

$router.push(숫자)

한번 뒤로가기

this.$router.go(-1)

페이지 새로고침

this.$router.go(0)

2. $route

$route는 현재 페이지에 대한 정보가 들어 있는객체

$route.params

$route.params.동적 라우팅으로 등록한 키워드
this.$route.params.id

$route.meta

this.$route.meta.메타이름
this.$route.meta.auth

댓글