본문 바로가기

Java Scripts/Vue.js

Vue : In-Component Route Guards

728x90

In-Component Route Guards

use In-Component Route Guards to show a progress bar and only load the component if it’s successfully returned from our API.

In-Component Route Guard를 사용하여 progress bar을 표시하고 API에서 성공적으로 반환된 경우에만 component를 로드합니다.

 

Problem: When our API is slow, our page looks broken

let our users know the data is on the way, and have something happen when they click a link that requires an API call.

사용자에게 데이터가 전송 중임을 알리고 API 호출이 필요한 링크를 클릭하면 어떤 일이 발생하도록 합니다.

 

There are two different ways to implement it.

  • In-component route guards. 
  • Global and per-route guards

Solution : In-Component Route Guards

  1. Install nprogress progress bar library.
  2. Move the API call into our beforeRouteEnter hook, so we ensure the API call is successful before we load the component.
  3. API 호출을 beforeRouteEnter hook로 이동하여 component를 로드하기 전에 API 호출이 성공했는지 확인합니다.
  4. Start the progress bar when routing to the component.
  5. component로 라우팅할 때 progress bar을 시작합니다.
  6. When API returns finish progress bar.
  7. API가 반환되면 progress bar를 종료한다..
  8. Ensure pagination works properly with the progress bar.
  9. progress bar을 사용하여 pagination이 제대로 작동하는지 확인하세요.

 

Install nprogress progress bar library.

NProgress need to be installed.

$ npm install nprogress

/src/main.js

add the CSS for NProgress

import 'nprogress/nprogress.css'

 

Move API call into an In-Component Route Guard

Vue gives us many different component lifecycle hooks, like created(), mounted(), updated(), etc. When using Vue Router, we get three more component hooks called  Navigation Guards | Vue Router (vuejs.org):

Vue는 created(), mounted (), updated () 등과 같은 component lifecycle hooks를 제공합니다.  Vue Router를 사용하면 Route Navigation Guards라는 세 가지 구성 요소 후크가 추가로 제공됩니다.

    beforeRouteEnter(routeTo, routeFrom, next)
    beforeRouteUpdate(routeTo, routeFrom, next)
    beforeRouteLeave(routeTo, routeFrom, next)
  • routeTo - This refers to the route that is about to be navigated to.
  • routeTo  - 탐색하려는 route를 나타냅니다.
  • routeFrom - This refers to the route that is about to be navigated away from.
  • routeFrom -  이는 탐색에서 빠져나오는 경로를 나타냅니다.
  • next - This is a function that can be called in each of them to resolve the hook, and continue navigation.
  • next - 이는 후크를 해결하고 탐색을 계속하기 위해 각각에서 호출할 수 있는 함수입니다.

 

beforeRouteEnter(routeTo, routeFrom, next)

This is called before the component is created. "this" keyword can't be used here.

이는 component가 생성되기 전에 호출됩니다. 여기서는 "this" 키워드를 사용할 수 없습니다.

If we want to set some reactive data inside our component, there’s a way to set it using the next.

component  내부에 일부 반응형 데이터를 설정하려면 next을 사용하여 이를 설정하는 방법이 있습니다.

 

beforeRouteUpdate(routeTo, routeFrom, next)

This is called when the route changes, is still using the same component.

이는 route 가 변경될 때 호출되며 여전히 동일한 component를 사용합니다.

When we paginate, and we switch from page to page but still using the same component. 

"this" is accessible.

페이지를 매길 때 페이지에서 페이지로 전환하지만 여전히 동일한 component를 사용합니다. this"에 액세스할 수 있습니다.

 

 

beforeRouteLeave(routeTo, routeFrom, next)

This is called when this component is navigated away from.

"this" is accessible.

 

 

Looking into Next

each of these methods at some point can call next()

Here’s what you can do with next:

 

  • next() - Called by itself will continue navigation to the component, which is referenced inside routeTo.
  • next() -  routeTo 가 reference 하는 component 로 navigation이 되게 한다.
  • next(false) - Cancels the navigation.
  • next(false) -  탐색을 취소합니다.
  • next('/') - Redirects page to the / path.
  • next('/') - 페이지를 / 경로로 리디렉션합니다.
  • next({ name: 'event-list' }) - Redirects to this named path
  • next({ name: 'event-list' }) - 이 명명된 경로로 리디렉션됩니다.

Any options that can be put in a router-link's to property can be sent into next() for redirecting navigation.

라우터 링크의 to 속성에 넣을 수 있는 모든 옵션은 redirecting navigation을 위해 next()로 보낼 수 있습니다.

 

beforeRouteLeave Example

If I want to confirm that the user wants to leave the page before saving changes, 

변경 사항을 저장하기 전에 사용자가 페이지를 떠나기를 원하는지 확인하려면,

  data: function() {
    return {
      unsavedChanges: false  // <-- Flag gets set to true if anything 
                             //          is changed on the form
    }
  },
  beforeRouteLeave(routeTo, routeFrom, next) {
    if (this.unsavedChanges) {
      const answer = window.confirm(
        'Do you really want to leave? You have unsaved changes!'
      )
      if (answer) {
        next() // <-- Confirms the navigation
      } else {
        next(false) // <-- Cancels the navigation
      }
    } else {
      next() // <-- Confirms the navigation
    }
  }

 

 

With the new version of Vue Router that ships with Vue 3. We can write this which is a little shorter. Instead of using next, we can use return values. 

Vue 3과 함께 제공되는 Vue Router의 새 버전을 사용하면 조금 더 짧게 작성할 수 있습니다. next를 사용하는 대신 반환 값을 사용할 수 있습니다.

  • No return value - Will continue navigation. 
  • No return value -  탐색을 계속합니다.
  • return true - Will continue navigation.
  • return true - 탐색을 계속합니다.
  • return false - Cancels the navigation.
  • return false - 탐색을 취소합니다.
  • return '/' - Redirects page to the / path.
  • return '/' - 페이지를 / 경로로 리디렉션합니다.
  • return { name: 'event-list' } - Redirects to this named path
  • return { name: 'event-list' } - 이 명명된 경로로 리디렉션됩니다.
  data: function() {
    return {
      unsavedChanges: false  // <-- Flag gets set to true if anything 
                             //          is changed on the form
    }
  },
  beforeRouteLeave(routeTo, routeFrom) {
    if (this.unsavedChanges) {
      const answer = window.confirm(
        'Do you really want to leave? You have unsaved changes!'
      )
      if (!answer) {
        return false // <-- Cancels the navigation
      }
    } 
  }

how might we use these with our EventList component?

/src/views/EventList.vue

this is the current codes designed

  created() {
    watchEffect(() => {
      this.events = null
      EventService.getEvents(2, this.page)
        .then(response => {
          this.events = response.data
          this.totalEvents = response.headers['x-total-count']
        })
        .catch(() => {
          this.$router.push({ name: 'NetworkError' })
        })
    })
  },

codes are changed.

Sending in a function to next will cause that function to be run inside the component once it’s loaded

next 로 함수를 보내면 해당 함수가 로드된 후 구성 요소 내에서 실행됩니다.

I’m using comp here to represent the Component,

여기서는 Component 를 나타내기 위해 comp를 사용하고 있습니다.

  beforeRouteEnter(routeTo, routeFrom, next) {
    NProgress.start()
    EventService.getEvents(2, parseInt(routeTo.query.page) || 1)
      .then(response => {
        next(comp => {
          comp.events = response.data
          comp.totalEvents = response.headers['x-total-count']
        })
      })
      .catch(() => {
        next({ name: 'NetworkError' })
      })
      .finally(() => {
        NProgress.done()
      })
  },

 

2  Installing the nprogress Progress Bar library

 

npm install nprogress

/src/main.js

   import 'nprogress/nprogress.css'

3. Start progress bar when routing to the component

4. When API returns finish progress bar

 

/src/views/EventList.vue

<script>
...
import NProgress from 'nprogress'

export default {
  name: 'EventList',
  props: ['page'],
  components: {
    EventCard
  },
  data() {
    return {
      events: null,
      totalEvents: 0
    }
  },
  beforeRouteEnter(routeTo, routeFrom, next) {
    NProgress.start()
    EventService.getEvents(2, parseInt(routeTo.query.page) || 1)
      .then(response => {
        next(comp => {
          comp.events = response.data
          comp.totalEvents = response.headers['x-total-count']
        })
      })
      .catch(() => {
        next({ name: 'NetworkError' })
      })
      .finally(() => {
        NProgress.done()
      })
  },
}
</script>

 

 

Problem: Pagination stopped working

 

Solution: beforeRouteUpdate

This is because beforeRouteEnter just like created doesn’t get run again if we navigate to the same component. Previously we fixed this with watchEffect which we can’t use anymore

이는 생성된 것처럼 beforeRouteEnter가 동일한 구성 요소로 이동하면 다시 실행되지 않기 때문입니다. 이전에는 watchEffect로 이 문제를 해결지만 더 이상 사용할 수 없습니다 

  beforeRouteUpdate(routeTo) {
    NProgress.start()
    EventService.getEvents(2, parseInt(routeTo.query.page) || 1)
      .then(response => {
        this.events = response.data
        this.totalEvents = response.headers['x-total-count']
      })
      .catch(() => {
        next({ name: 'NetworkError' })
      })
      .finally(() => {
        NProgress.done()
      })
  },

BeforeRouteUpdate does have access to this , so we can set our event data using this , and simply call next().

BeforeRouteUpdate는 this에 액세스할 수 있으므로 this를 사용하여 이벤트 데이터를 설정하고 간단히 next()를 호출할 수 있습니다.

 

Resources

GitHub - Code-Pop/Touring-Vue-Router at L9-end

 

Release progressbar-in-component-route-guard-finish · Code-Pop/real-world-vue

Using In-Component Route Guard

github.com

 

 

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

 

Navigation Guards | Vue Router

Navigation Guards As the name suggests, the navigation guards provided by Vue router are primarily used to guard navigations either by redirecting it or canceling it. There are a number of ways to hook into the route navigation process: globally, per-route

router.vuejs.org

 

'Java Scripts > Vue.js' 카테고리의 다른 글

Vuex : Success & Error Notifications  (0) 2022.05.06
Vuex - Modules  (0) 2022.05.04
Vue : Flash Messages  (0) 2022.05.01
Vue : Programmatic Navigation  (0) 2022.04.30
Vuex - Mutation & Action - 2  (0) 2022.04.18