Spec-Zone.ru › Vue Router 3

Защитники навигации

Как следует из названия, защитники навигации, предоставляемые vue-router, в основном используются для защиты навигации, либо перенаправляя её, либо отменяя. Есть несколько способов подключиться к процессу навигации по маршрутам: глобально, по маршруту или в компоненте.

Помните, что изменения параметров или запроса не будут запускать защитники навигации enter/leave. Вы можете либо отслеживать объект $route, чтобы реагировать на эти изменения, либо использовать защитник в компоненте beforeRouteUpdate

Глобальные защитники перед навигацией

Узнайте, как работают защитники навигации с бесплатным уроком на Vue School

Вы можете зарегистрировать глобальные защитники перед навигацией, используя router.beforeEach

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

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

Глобальные защитники перед навигацией вызываются в порядке регистрации всякий раз, когда запускается навигация. Защитники могут быть решены асинхронно, и навигация считается ожидающей до тех пор, пока все обработчики не будут решены.

Каждая функция-защитник получает три аргумента:

  • to: Route: целевой объект маршрута, к которому осуществляется навигация.

  • from: Route: текущий маршрут, от которого осуществляется навигация.

  • next: Function: эту функцию необходимо вызвать, чтобы разрешить обработчик. Действие зависит от аргументов, переданных в next:

    • next(): перейти к следующему обработчику в цепочке. Если больше нет обработчиков, навигация подтверждается.

    • next(false): прервать текущую навигацию. Если адрес браузера был изменен (либо вручную пользователем, либо с помощью кнопки "Назад"), он будет сброшен до адреса маршрута from.

    • next('/') или next({ path: '/' }): перенаправить в другое место. Текущая навигация будет прервана, и начнется новая. Вы можете передать любой объект местоположения в next, что позволит указать параметры, такие как replace: true, name: 'home' и любые параметры, используемые в router-link свойстве to или router.push

    • next(error): (2.4.0+) если аргумент, переданный в next, является экземпляром Error, навигация будет прервана, а ошибка будет передана в обратные вызовы, зарегистрированные через router.onError().

Убедитесь, что функция next вызывается ровно один раз при каждом проходе через защитник навигации. Она может появляться более одного раза, но только если логические пути не перекрываются, в противном случае обработчик никогда не будет разрешен или приведет к ошибкам. Вот пример перенаправления пользователя на /login, если он не авторизован:

// BAD
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  // if the user is not authenticated, `next` is called twice
  next()
})
// GOOD
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})

Глобальные защитники разрешения

Вы можете зарегистрировать глобальный защитник с помощью router.beforeResolve. Это похоже на router.beforeEach, с той разницей, что защитники разрешения будут вызваны непосредственно перед подтверждением навигации, после разрешения всех защитников в компонентах и асинхронных компонентов маршрута.

Глобальные обработчики после навигации

Вы также можете зарегистрировать глобальные обработчики после навигации, однако, в отличие от защитников, эти обработчики не получают функцию next и не могут повлиять на навигацию:

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

Защитник по маршруту

Вы можете определить защитники beforeEnter непосредственно в объекте конфигурации маршрута:

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

Эти защитники имеют тот же самый синтаксис, что и глобальные защитники перед навигацией.

Защитники в компонентах

Наконец, вы можете непосредственно определить защитники навигации по маршрутам внутри компонентов маршрутов (тех, что передаются в конфигурацию маршрутизатора) с помощью следующих вариантов:

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
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.
    // This component being reused (by using an explicit `key`) in the new route or not doesn't change anything.
    // 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 (unless you provided a `key` to `<router-view>`), 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 НЕ имеет доступа к this, так как он вызывается до подтверждения навигации, и новый входящий компонент еще не создан.

Однако, вы можете получить доступ к экземпляру, передав обратный вызов в next. Обратный вызов будет вызван, когда навигация будет подтверждена, и экземпляр компонента будет передан обратного вызову в качестве аргумента:

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

Обратите внимание, что beforeRouteEnter — единственный защитник, который поддерживает передачу обратного вызова в next. Для beforeRouteUpdate и beforeRouteLeave, this уже доступен, поэтому передача обратного вызова не требуется и, следовательно, не поддерживается:

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

Защитник выхода обычно используется для предотвращения случайного выхода из маршрута с несохраненными изменениями. Навигация может быть отменена путем вызова 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)
  }
}

Если вы используете миксины, которые добавляют защитники навигации в компоненты, убедитесь, что вы добавили миксин после установки плагина маршрутизатора:

Vue.use(Router)

Vue.mixin({
  beforeRouteUpdate(to, from ,next) {
    // ...
  }
})

Полный поток разрешения навигации

  1. Запущена навигация.
  2. Вызов защитников beforeRouteLeave в деактивированных компонентах.
  3. Вызов глобальных защитников beforeEach.
  4. Вызов защитников beforeRouteUpdate в повторно используемых компонентах.
  5. Вызов защитников beforeEnter в конфигурациях маршрутов.
  6. Разрешение асинхронных компонентов маршрута.
  7. Вызов защитников beforeRouteEnter в активированных компонентах.
  8. Вызов глобальных защитников beforeResolve.
  9. Навигация подтверждена.
  10. Вызов глобальных обработчиков afterEach.
  11. Запускаются обновления DOM.
  12. Вызов обратных вызовов, переданных в next в beforeRouteEnter защитниках с созданными экземплярами.

← Режим истории HTML5 Поля метаданных маршрута →

© 2013–present Evan You
Licensed under the MIT License.
https://router.vuejs.org/guide/advanced/navigation-guards.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API