vue create vue-router-app
cd vue-router-app
vue add router

vue 프로젝트 생성, 디렉토리 이동, vue cli를 통해 router plugin 적용

 

 

주소를 이동하는 방법 2가지

1. 선언적 방식 네비게이션

      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>

router-link의 to 속성으로 주소 전달

routes에 등록된 주소와 매핑된 컴포넌트로 이동

 

 

 

Named Routes

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue')
  }
]

index.js

이름을 가지는 rotes, django에서 path함수의 name인자 활용방식과 같다.

 

      <router-link :to="{name : 'home'} ">Home</router-link> |
      <router-link :to="{name : 'about'} ">About</router-link>

index.js의 routes에 지정한 name으로 주소를 이동한다.

to 속성으로 주소를 전달하는데 name을 이용한다.

동적인 값을 사용하기 때문에 v-bind를 사용해서 자바스크립트 표현식으로 작성한다.

v-bind를 사용하지 않으면 입력한 문자 그대로 주소가 되버린다.

 

 

2. 프로그래밍 방식 네비게이션

<template>
  <div class="about">
    <button @click="toHome"> 프로그래밍 방식으로 Home으로!</button>
  </div>
</template>
<script>
export default {
  name : 'AboutView',
  methods : {
    toHome(){
      this.$router.push({name : 'home'})
    }
  }
}
</script>

AboutView.vue

 

Vue 인스턴스 내부에서 라우터인스턴스에 $router로 접근할 수 있다.

다른 URL로 이동하려면 this.$router.push를 사용한다.

history stack에 이동할 URL을 넣는(push) 방식이다. 

history stack에 기록이 남기 때문에 뒤로가기 기능 사용할 수 있다.

<router-link : to = "...">를 클릭하는 것과 $router.push(...)를 호출하는 것은 같은 동작이다.

 

동작 원리는 선언적 방식과 같다.

 

 

 

 

Dynamic Route Matching (동적 인자 전달)

URL의 특정 값을 변수처럼 사용할 수 있다.

Django에서의 variable routing이다.

 

import HelloView from '../views/HelloView.vue'

const routes = [
  {
    path: '/hello/:userName',
    name : 'hello',
    component : HelloView
  }
]

index.js

HelloView.vue 작성하고 route 추가했다.

route 추가할 때 : 으로 동적인자를 명시했다. (:userName) 

(django에서는 <>를 이용했다.)

 

 

 

<template>
  <div>
    <h1>hello, {{$route.params.userName}} </h1>
  </div>
</template>

views/HelloView.vue

$route.params.변수명으로 변수에 접근 가능하다.

변수명은 route에서 지정해준 것이다.

 

주소를 직접 입력해서 들어갔더니 주소에 입력한 "이름" 이라는 것을 사용해서 화면에 보여준 것이다.

 

<template>
  <div>
    <h1>hello, {{userName}} </h1>
  </div>
</template>

<script>
export default {
    name:'HelloView',
    data(){
        return {
            userName : this.$route.params.userName
        }
    }
}
</script>

HelloView.vue

하지만, HTML에서 직접사용하는 것 보다 data에 넣어서 사용하는 것이 좋다.

 

 

<template>
  <div id="app">
    <nav>
      <router-link :to="{name : 'home'} ">Home</router-link> |
      <router-link :to="{name : 'about'} ">About</router-link> |
      <router-link :to="{name : 'hello', params : {userName : 'harry'} }">hello</router-link>
    </nav>
    <router-view/>
  </div>
</template>

App.vue

App.vue에서 harry에게 인사하는 페이지로 이동한다.

파라미터 값을 같이 보내주어야 하기 때문에 params로 key, value 값 보내준 다.

params를 이용하여 동적인자 전달 가능하다.

 

hello를 클릭하면 위와 같이 주소, 화면이 바뀐다.

 

위 예시는 params의 userName은 직접 입력한 데이터만 사용하는 것이다.

파라미터를 직접입력하지 않고 변수로 사용할 수 있다.

 

 

AboutView에서 데이터를 입력받아 HelloView로 이동하여 입력받은 데이터에게 인사하기

<template>
  <div class="about">
    <button @click="toHome"> 프로그래밍 방식으로 Home으로!</button>
    <input 
    type="text"
    @keyup.enter = "Hello"
    v-model="input"
    >
  </div>
</template>
<script>
export default {
  name : 'AboutView',
  data(){
    return{
      input : null,
    }
  },
  methods : {
    toHome(){
      this.$router.push({name : 'home'})
    },
    Hello(){
      this.$router.push({name:'hello',params : {userName : this.input }})
    }
  }
}
</script>

input 태그에 입력한 값을 v-model로 연결해주었고,

keyup.enter 동작시 Hello 메서드 실행한다.

Hello메서드는 this.$router.push()로 특정 route로 이동하도록 한다.

name은 hello로 지정되어 있던 route이고, params로 필요한 파라미터 인자를 보내준다. userName이라는 파라미터 값이 필요하기 때문에 this.input으로 v-model 연결한 데이터를 보내준다.

 

 

      this.$router.push( {path : `hello/${this.input}`})

이렇게 직접 path를 지정해주어도 된다.

 

 

 

 

 

lazy-loading

모든 파일을 한번에 로드하려고하면 모든 걸 다 읽는데 시간이 오래걸린다.

미리 로드를 하지 않고 특정 라우트에 방문할 때 매핑된 컴포넌트의 코드를 로드하는 방식을 활용할 수 있다.

모든 파일을 한번에 로드하지 않아도 되기 때문에 최초에 로드하는 시간이 빨라진다.

당장 사용하지 않는 컴포넌트는 먼저 로드하지 않는 것이다.

 

 

import HomeView from '../views/HomeView.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue')
  },
 
]

home은 미리 로드하는 방식이고, 첫 로딩에 렌더링 된다.

about이 lazy-loading 방식이다. 첫로딩에 렌더링 하지 않고 해당 라우터가 동작할 때 컴포넌트를 렌더링 한다.

component에 값을 넣지않고 route가 동작할때 component를 가져올 함수를 실행하도록 한다.

화살표함수 () => import() 방식으로 작성하면 된다.

 

 

 

Navigation Guard (네비게이션 가드)

Vue router를 통해 특정 URL에 접근할 때 다른 URL로 redirect하거나 해당 URL로의 접근을 막는 방법

ex. 사용자 인증 정보가 없으면 특정 페이지에 접근하지 못하게 함

 

네비게이션 가드 종류

- 전역 가드 : 애플리케이션 전역에서 동작

- 라우터 가드 : 특정 URL에서만 동작

- 컴포넌트 가드 : 라우터 컴포넌트 안에 정의

 

 

전역가드 (Global Before Guard)

다른 url 주소로 이동할 때 항상 실행

router/index.js에 router.beforeEach()를 사용하여 설정

콜백 함수의 값으로 3개의 인자를 받는다.

- to : 이동할 url 정보가 담긴 route 객체

- from : 현재 url 정보가 담긴 route 객체

- next : 지정한 url로 이동하기 위해 호출하는 함수 (콜백 함수 내부에서 반드시 한번만 호출되어야 함, 기본적으로 to에 해당하는 url로 이동)

 

URL이 변경되어 화면이 전환되기 전 router.beforeEach()가 호출된다.

(화면이 전환되지 않고 대기상태가 됨)

변경된 URL로 라우팅 하기 위해서는 next()를 호출해줘야 한다. next()가 호출되기 전까지 화면이 전환되지 않는다.

 

router.beforeEach((to,from,next) => {
  console.log('to',to)
  console.log('from',from)
  console.log('next',next)
  next()
})

index.js

to, from, next 인자를 확인하기위해 console에 출력했다.

home에서 about을 이동하려고 클릭했을 때 beforeEach가 호출된다.

to는 이동할 url 정보가 담긴 route객체, from은 현재 url정보가 담긴 route객체이다.

next는 이동하기 위한 함수이다.

next()를 호출해야 이동한다.

next()가 호출되지 않으면, 로그만 출력되고 화면이 전환되지 않는다.

 

 

Login 여부에 따른 라우팅 처리

Login이 되어 있지 않다면 Login 페이지로 이동하는 기능을 추가한다.

 

  {
    path: '/login',
    name : 'login',
    component : LoginView
  }

views에 LoginView.vue를 생성하고,

router/index.js에 login route 만든다.

 

 

<template>
  <div id="app">
    <nav>
      <router-link :to="{name : 'home'} ">Home</router-link> |
      <router-link :to="{name : 'about'} ">About</router-link> |
      <router-link :to="{name : 'hello', params : {userName : 'harry'} }">hello</router-link> |
      <router-link :to="{name : 'login'}">Login</router-link>
    </nav>
    <router-view/>
  </div>
</template>

App.vue

LoginView에 대한 라우터 링크를 추가한다.

 

 

router.beforeEach((to,from,next) => {
  const isLoggedIn = true
  const authPages = ['hello']
  const isAuthRequired = authPages.includes(to.name)
  if (isAuthRequired && !isLoggedIn){ //로그인이 필요한 페이지 & 로그인 되어있지 않음
    next({name : 'login'})
  } else {
    next()
  }
})

index.js

HelloView에 로그인 해야만 접근할 수 있도록 만들어 본다.

로그인 여부에 대한 임시 변수를 생성한다.

로그인이 필요한 페이지를 저장한다. (로그인이 필요한 페이지들의 이름을 작성한다.)

앞으로 이동할 페이지가 로그인이 필요한 사이트인지 확인한다.

로그인이 필요한 사이트이고, 로그인되어있지 않으면 로그인페이지로 이동한다. 그렇지 않으면, 이동하려고 했던 페이지(기존 루트)로 이동한다. 

next()인자가 없을 경우 to로 이동한다.

isLoggedIn 변수를 false로 지정하고, hello 페이지로 이동하려고 한다. 로그인이 필요한 페이지이고 로그인여부가 false이기 때문에 hello를 클릭했을 때 hello페이지가 아니고 로그인페이지로 이동된다.

로그인 해야 하는 페이지가 많을 때 반대로 login하지 않아도 되는 페이지들을 모아둘 수도 있다.

 

 

라우터 가드 (beforeEnter)

전체 route가 아닌 특정 route에 대해서만 가드를 설정하고 싶을 때 사용

beforeEnter()

route에 진입했을 때 실행됨

라우터를 등록한 위치에 추가

단 매개변수, 쿼리, 해시 값이 변경될 때는 실행되지 않고 다른 경로에서 탐색할 때만 실행된다.

콜백 함수는 to, from, next를 인자로 받는다.

 

 

Login 여부에 따른 라우팅 처리

로그인페이지로 갈때 이미 로그인 되어 있는 경우 HomeView로 이동하기

전역 가드로 라우팅 처리한 것은 주석처리한다.

 

 

const isLoggedIn = true
 {
    path: '/login',
    name : 'login',
    component : LoginView,
    beforeEnter(to,from,next){
      if (isLoggedIn ===true){
        console.log('이미 로그인 됨')
        next({name :'home'})
      } else {
        next()
      }
    }
  }

index.js

로그인 여부에 대한 임시 변수를 생성하고,

로그인이 되어있는 경우 home으로 이동하고 로그인이 되어있지 않은경우 login으로 이동하게 한다.

isLoggedIn이 true인 경우에 login 페이지로 이동하려고 해도 home으로 이동하게 된다.

false인 경우에는 login페이지로 잘 이동된다.

 

라우터 가드는 특정 라우터에만 가드를 설정하는 것이기 때문에 login route에서 처리한 것이다.

login을 제외한 다른 페이지로 이동하면 라우터가드를 따로 설정해주지 않았기 때문에 라우터 가드가 동작하지 않는다. 특정 라우트만 따로 가드하고 싶을 때 라우터 가드를 사용한다.

 

 

 

컴포넌트 가드 (beforeRouteUpdate())

특정 컴포넌트 내에서 가드를 지정하고 싶을 때 사용

beforeRouteUpdate()

해당 컴포넌트를 렌더링하는 경로가 변경될 때 실행된다.

 

 

Params 변화 감지

about에서 input에 jun을 입력하여 jun에게 인사하는 페이지로 이동했다. (hello/jun)

 

 

navbar에 있는 Hello를 눌러 harry에게 인사하는 페이지로 이동했는데, url은 hello/harry로 변했지만 페이지는 hello, jun 내용이 그대로이다.

/hello/:userName 에서 userName변수가 변경되어도 url 변경되었다고 인식하지 못하는 것이다.

컴포넌트가 재사용되어, 기존컴포넌트를 지우고 새로 만드는 것보다 효율적이기 때문에 변화하지 않았다.

lifecycle hook이 호출되지 않았고, $route.params에 있는 데이터를 새로 가져오지 않았다.

 

 

export default {
    name:'HelloView',
    data(){
        return {
            userName : this.$route.params.userName
        }
    },
    beforeRouteUpdate(to,from,next){
      this.userName = to.params.userName
      next()
    }
}

HelloView.vue

해당 컴포넌트가 다른 주소로 렌더링될때에 대한 처리를 한다.

beforeRouteUpdate()를 사용한다.

userName을 이동할 params에 있는 userName으로 재할당한다.

해당 컴포넌트를 렌더링하는 경로가 hello/jun 에서 hello/harry로 변경되었다. 이때 컴포넌트 가드가 처리된다.

 

 

 

 

 

'Front-end > Vue.js' 카테고리의 다른 글

404 Not Found  (0) 2022.11.09
Articles with Vue - CRUD  (0) 2022.11.09
Routing , Vue Routing 시작하기  (0) 2022.11.09
UX & UI / Prototyping  (0) 2022.11.09
Vuex를 사용한 Todo 프로젝트 만들기 / Local Storage, vuex-persistedstate  (0) 2022.11.07