VueJS: Guard điều hướng

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Guard điều hướng được cung cấp bởi vue-router chủ yếu được sử dụng để bảo vệ khi chuyển hướng hoặc hủy bỏ nó. Có một số cách để tham gia vào quá trình điều hướng route: toàn cục, trên mỗi route hoặc trong component.

Lưu ý là các param hay query thay đổi sẽ không kích hoạt guard điều hướng enter/leave. Ta có thể watch đối tượng $route để phản ứng với những thay đổi này, hoặc sử dụng guard trong component beforeRouteUpdate.

Guard global

Ta có thể đăng ký global trước khi guard bằng cách sử dụng router.beforeEach:

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

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

Guard này được gọi theo thứ tự nó được tạo ra mỗi khi các điều hướng được kích hoạt. Guard có thể được giải quyết không đồng bộ và điều hướng được xem là pending trước khi tất cả các hook được giải quyết.

Mỗi hàm guard sẽ nhận 3 đối số:

  • to: Route: Chuyển hướng tới đối tượng route.

  • from: Route: route hiện thời được chuyển hướng đi.

  • next: Function: hàm này phải được gọi để giải quyết hook. Các hành động giải quyết cụ thể phụ thuộc vào các đối số được cung cấp cho next:

    • next(): di chuyển sang hook tiếp theo trong pipeline. Nếu không còn hook nào thì chuyển hướng được xác nhận.

    • next(false): bỏ qua điều hướng hiện thời. Nếu URL trình duyệt thay đổi (theo cách thủ công của người dùng hoặc thông qua nút back của trình duyệt) thì nó sẽ được reset thành route from.

    • next('/') hoặc next({ path: '/' }): chuyển hướng đến một vị trí khác. Điều hướng hiện thời sẽ bị bỏ qua và một điều hướng mới sẽ được kích hoạt. Ta có thể truyền bất kỳ đối tượng location nào tới next mà cho phép bạn xác định được các tùy chọn dạng replace: truename: 'home' và tùy chọn bất kỳ được sử dụng trong prop to của router-link hoặc router.push

    • next(error): (2.4.0+) nếu đối số truyền tới next là một đối tượng Error thì điều hướng sẽ được bỏ qua và lỗi sẽ được truyền tới callback đã được đăng ký thông qua router.onError().

Hãy chắc chắn rằng bạn luôn gọi hàm next, nếu không thì hook sẽ không bao giờ được giải quyết.

Guard resolve

Ta có thể đăng ký guard global router.beforeResolve. Nó tương tự router.beforeEach nhưng khác ở chỗ guard resolve sẽ được gọi trước khi điều hướng được xác nhận, sau tất cả các guard in-component và các route component bất đồng bộ được giải quyết..

Hook after

Ta cũng có thể đăng ký hook after, tuy nhiên thì không giống như guard, các hook này không lấy hàm next và không thể ảnh hưởng đến điều hướng:

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

Guard cho từng route

Ta có thể định nghĩa guard beforeEnter trực tiếp trong cấu hình route:

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

Những guard dạng này giống như guard before.

Guard in-component

Cuối cùng, ta có thể trực tiếp định nghĩa guard điều hướng route bên trong các component route (được truyền tới cấu hình router) với các tùy chọn sau:

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // được gọi trước route mà render component này được xác nhận.
    // không truy cập tới đối tượng component `this`,
    // trước khi nó được tạo khi guard này được gọi!
  },
  beforeRouteUpdate (to, from, next) {
    // được gọi khi route render component này thay đổi,
    // nhưng component này vẫn tái sử dụng trong route mới.
    // Ví dụ, route với tham số động `/foo/:id`, khi ta
    // điều hướng giữa `/foo/1` và `/foo/2` thì đối tượng component `Foo`
    // vẫn được sử dụng, và hook này sẽ được gọi khi điều đó xảy ra.
    // truy cập tới đối tượng component `this`.
  },
  beforeRouteLeave (to, from, next) {
    // được gọi khi route render component này
    // được chuyển hướng rời đi.
    // truy cập đối tượng component `this`.
  }
}

Guard beforeRouteEnter không có quyền truy cập this bởi vì guard được gọi trước khi các điều hướng được xác nhận, vì thế mà component nhập mới cũng không được tạo.

Tuy nhiên, ta có thể thuy cập đối tượng bằng cách truyền callback tới next. Callback sẽ được gọi khi điều hướng được xác nhận, và đối tượng component sẽ được truyền tới callback dưới dạng đối số:

beforeRouteEnter (to, from, next) {
  next(vm => {
    // truy cập tới đối tượng component thông qua `vm`
  })
}

Lưu ý là beforeRouteEnter là guard duy nhất hỗ trợ việc truyền callback tới next. Còn đối với beforeRouteUpdate và beforeRouteLeave thì do đã có sẵn this cho nên không cần dùng đến callback:

beforeRouteUpdate (to, from, next) {
  // dùng `this`
  this.name = to.params.name
  next()
}

Guard leave thường được dùng để ngăn không cho người dùng vô tình rời khỏi route mà không lưu các chỉnh sửa. Điều hướng có thể bị huy bằng lời gọi 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)
  }
}

Luồng phân giải điều hướng đầy đủ

  1. Điều hướng được kích hoạt.
  2. Gọi các guard leave các component đã vô hiệu hóa.
  3. Gọi guard global beforeEach.
  4. Gọi guard beforeRouteUpdate trong các component tái sử dụng.
  5. Gọi beforeEnter trong cấu hình route.
  6. Giải quyết các component route bất đồng bộ.
  7. Gọi beforeRouteEnter trong các component được active.
  8. Gọi guard global beforeResolve.
  9. Điều hướng được xác nhận.
  10. Gọi các hook global afterEach.
  11. Cập nhật DOM được kích hoạt.
  12. Gọi các callback được truyền tới next trong các guard beforeRouteEnter với các đối tượng được khởi tạo.
» Tiếp: Giới thiệu Nuxt.js
« Trước: Khớp route động
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!