티스토리 뷰

Vue.JS

[vue-router] 네비게이션 가드

버미노트 2019. 6. 15. 00:49

네비게이션 가드는 이름에서 알 수 있듯이 리다이렉션하거나 취소하여 네비게이션을 보호하는데 사용됩니다. 전역, 라우트별, 컴포넌트별로 네비게이션 가드를 등록하여 사용할 수 있습니다. 이번 포스트에서는 전역, 라우트별, 컴포넌트 각각의 방법으로 네비게이션 가드를 등록하는 방법을 이야기 하도록 하겠습니다.
params나 query가 변경되어도 네비게이션 가드는 실행되지 않습니다. 변경되는 시점을 알고 싶다면, vue 옵션 중 watch 옵션에 $router 객체를 등록하거나 컴포넌트 가드인 beforeRouteUpdate(2.2 버전에서 추가 됨)를 사용해야 합니다.

1. Global Before 가드

router.beforeEach를 사용하여 Gobal Before 가드를 사용할 수 있습니다.

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

Gobal Before 가드는 모든 네비게이션의 생성된 순서에 따라 호출 됩니다. 이 가드는 비동기적으로 종료(resolved) 될 수 있습니다. 모든 훅들이 종료(resolved)되기 전까지 네비게이션은 중지된 상태가 됩니다.

Global Before 가드의 전달인자

  • to: Route : 이동할 타켓의 Route 객체입니다.
  • from: Route : 현재의 Route 객체(네비게이션 이동하기 전의 Route 객체)입니다.
  • next: Function : 이 함수를 호출해야 훅이 종료(resolved) 됩니다. 어떠한 동작을 할 것인지는 next 함수어 어떤 인자값이 전달되는지에 따라 결정됩니다.
    • next() : 다음 훅으로 이동됩니다. 다른 훅으로 이동할 수 있도록 승인을 하는 동작입니다.
    • next(false) : 현재 네비게이션을 종료합니다.
    • next('/') 또는 next({ path: '/' }) : 인자로 전달된 경로로 이동합니다. 현재의 네비게이션은 중단되고 새로운 네비게이션이 시작됩니다. next 함수에는 replace: truename: 'home', <router-link>to에 전달되어야 하는 prop나 router.push 함수에 전달되어야 하는 값들 모두 인자값으로 사용 가능합니다.
    • next(error) : (2.4.0 이후) next 함수에 전달된 값이 Error 인스턴스이면, 네비게이션이 중지되고, 에러는 router.onError()의 콜백에 전달됩니다.

next 함수는 항상 호출되어야 합니다. 호출되지 않으면 훅은 종료되지 않습니다.

2. Global Resolve 가드

router.beforeResolve를 사용하여 Global 가드를 등록할 수 있습니다. router.beforeEach와 유사합니다. 차이점은 모든 in-component 가드와 비동기 라우터 컴포넌트가 종료 된 후, 네비게이션이 승인되기 바로 전에 호출된다는 것입니다.

3. Global After 훅

router.afterEach를 사용하여 Global 훅을 등록할 수 있습니다. 가드라고 이야기하지 않고 훅이라고 이야기 한 이유는 네비게이션을 보호하는 가드의 역할을 하는 next 함수가 인자로 전달되지 않기 때문입니다.

router.afterEach((to, from) => {
  // ...
})

4. Route 별 가드

beforeEnter 가드는 route 설정 객체에 직접 정의하여 사용합니다.

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

5. 컴포넌트 내부 가드

라우트 컴포넌트 내부의 네비게이션 가드를 정의 할 수 있습니다. 컴포넌트 내부 가드는 beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave 3가지가 있습니다.

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // called before the route that renders this component is confirmed.
    // does NOT have access to `this` component instance,
    // because it has not been created yet when this guard is called!
  },
  beforeRouteUpdate (to, from, next) {
    // called when the route that renders this component has changed,
    // but this component is reused in the new route.
    // For example, for a route with dynamic params `/foo/:id`, when we
    // navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
    // will be reused, and this hook will be called when that happens.
    // has access to `this` component instance.
  },
  beforeRouteLeave (to, from, next) {
    // called when the route that renders this component is about to
    // be navigated away from.
    // has access to `this` component instance.
  }
}

beforeRouteEnter 가드

beforeRouteEnter 가드는 네비게이션이 승인된기 전(새로 진입하는 컴포넌트가 생성되기 전)에 호출되기 때문에 this를 사용할 수 없습니다. 하지만 next 함수의 콜백은 네비게이션이 승인 된후 호출 되기 때문에 이 콜백을 사용하여 컴포넌트 인스턴스에 접근할 수 있습니다.

beforeRouteEnter (to, from, next) {
  next(vm => {
    // access to component instance via `vm`
  })
}

beforeRouteEnter에서만 next 함수의 콜백함수를 지원합니다.

beforeRouteUpdate 가드

beforeRouteUpdate 가드에서는 this를 사용할 수 있습니다. next의 콜백함수를 지원할 필요가 없어 next의 콜백함수를 지원하지 않습니다.

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

beforeRouteLeave 가드

beforeRouteLeave 가드는 에디터가 값을 저장하지 않고 페이지를 벗어나는 것을 방지하는데 유용한 가드입니다. next(false)를 호출하면 네비게이션이 중단됩니다.

beforeRouteLeave (to, from, next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

6. 전체 네비게이션 시나리오

  1. 네비게이션이 트리거 됨.
  2. 비활성되 된 컴포넌트에서 Leave 가드가 호출 됨.
  3. 전역 가드인 beforeEach 가드가 호출 됨.
  4. 재사용 된느 컴포넌트에서 beforeRouteUpdate 가드가 호출 됨.
  5. route 설정에 정의 된 beforeEnter 가드가 호출 됨.
  6. 비동기 라우터 컴포넌트가 해결 됨.
  7. 활성화 되는 컴포넌트의 beforeRouteEnter 가드가 호출 됨.
  8. 전역 가드인 beforeResolve 가드가 호출 됨.
  9. 네비게이션이 완료 됨.
  10. 전역 훅인 afterEach 훅이 호출 됨.
  11. DOM 업데이트가 트리거 됨.
  12. beforeRouteEnter 가드의 next 함수에 전달된 콜백 함수가 호출 됨.

참고

'Vue.JS' 카테고리의 다른 글

[vue-router] 트랜지션  (0) 2019.06.16
[vue-router] 라우터 메타 필드  (0) 2019.06.16
[vue-router] HTML5 히스토리 모드  (0) 2019.06.14
[vue-router] 라우터 컴포넌트에 props 전달  (0) 2019.06.13
[vue-router] Redirect 와 Alias  (0) 2019.06.12
댓글
공지사항
최근에 올라온 글