File: navigation-guards.md

package info (click to toggle)
vue-router.js 3.4.9%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,212 kB
  • sloc: javascript: 7,982; sh: 22; makefile: 5
file content (154 lines) | stat: -rw-r--r-- 10,410 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Сторожевые хуки

Как следует из названия, сторожевые хуки `Vue-router` используются для редиректов или отмены навигационных переходов. Есть несколько способов внедрить сторожевой хук: глобально, для конкретного пути, или для конкретного компонента.

Следует помнить, что **изменение параметров маршрута не вызывает выполнения сторожевых хуков enter/leave**. Вы можете добавить [watch на объект `$route`](../essentials/dynamic-matching.md#отслеживание-изменений-параметров) для отслеживания этих изменений, или использовать хук `beforeRouteUpdate`.

### Глобальные хуки

Глобальный хук можно зарегистрировать через `router.beforeEach`:

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

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

Глобальные сторожевые хуки вызываются в порядке создания при каждом навигационном переходе. Допускается асинхронное разрешение хуков — в этом случае переход считается **незавершённым** до тех пор, пока не будут разрешены все хуки.

В каждый сторожевой хук передаётся три параметра:

- **`to: Route`**: целевой [объект Route](../api/route-object.md), к которому осуществляется переход.

- **`from: Route`**: текущий путь, с которого осуществляется переход к новому.

- **`next: Function`**: функция, вызов которой **разрешает** хук. В зависимости от переданных в `next` аргументов, результатом будет:

  - **`next()`**: переход к следующему хуку в цепочке. Если хуков больше нет, переход считается **подтверждённым**.

  - **`next(false)`**: отмена перехода. Если URL был изменён (вручную пользователем, или кнопкой "назад"), он будет сброшен на соответствующий пути `from`.

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

  - **`next(error)`**: (добавлено в версии 2.4.0+) если аргумент, переданный `next` является экземпляром `Error`, навигация будет прервана и ошибка будет передана в коллбек, зарегистрированный через [`router.onError()`](../api/router-instance.html#методы).

**Удостоверьтесь, что функция `next` так или иначе будет вызвана, иначе хук никогда не будет разрешён.**

### Глобальные хуки разрешения перехода

> Добавлено в версии 2.5.0

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

### Глобальные хуки завершения перехода

Можно также зарегистрировать глобальные хуки, вызываемые после завершения перехода. Однако, в отличие от сторожевых хуков, в них не передаётся функция `next`, и на ход перехода они повлиять не могут:

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

### Указание хука для конкретного пути

Сторожевые хуки `beforeEnter` можно указать напрямую для конкретного пути в его конфигурации:

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

Эти хуки ничем не отличаются от глобальных.

### Указание хука для конкретного компонента

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

- `beforeRouteEnter`
- `beforeRouteUpdate` (добавлено в версии 2.2+)
- `beforeRouteLeave`

``` js
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // вызывается до подтверждения пути, соответствующего этому компоненту.
    // НЕ имеет доступа к контексту экземпляра компонента `this`,
    // так как к моменту вызова экземпляр ещё не создан!
  },
  beforeRouteUpdate (to, from, next) {
    // вызывается когда маршрут, что рендерит этот компонент изменился,
    // но этот компонент будет повторно использован в новом маршруте.
    // Например, для маршрута с динамическими параметрами `/foo/:id`, когда мы
    // перемещаемся между `/foo/1` и `/foo/2`, экземпляр того же компонента `Foo`
    // будет использован повторно, и этот хук будет вызван когда это случится.
    // Также имеется доступ в `this` к экземпляру компонента.
  },
  beforeRouteLeave (to, from, next) {
    // вызывается перед переходом от пути, соответствующего текущему компоненту;
    // имеет доступ к контексту экземпляра компонента `this`.
  }
}
```

Хук `beforeRouteEnter` **НЕ** имеет доступа к `this`, так как к моменту его вызова навигация ещё не подтверждена, а значит и экземпляр компонента ещё не создан.

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

``` js
beforeRouteEnter (to, from, next) {
  next(vm => {
    // экземпляр компонента доступен как `vm`
  })
}
```

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

```js
beforeRouteUpdate (to, from, next) {
  // просто используйте `this`
  this.name = to.params.name
  next()
}
```

**Сторожевой хук ухода со страницы** обычно используется для предотвращения случайного ухода пользователя со страницы с несохранёнными изменениями. Навигацию можно отменить вызовом `next(false)`.

```js
beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Вы действительно хотите уйти? У вас есть несохранённые изменения!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}
```

### Полная цепочка обработки навигации

1. Срабатывание навигации.
2. Вызов leave-хуков в деактивируемых компонентах.
3. Вызов глобальных `beforeEach` хуков.
4. Вызов `beforeRouteUpdate` хука в переиспользуемых компонентах (2.2+).
5. Вызов `beforeEnter` в конфигурации маршрута.
6. Разрешение асинхронных компонентов для маршрута.
7. Вызов `beforeRouteEnter` в активируемых компонентах.
8. Вызов глобальных `beforeResolve` хуков (2.5+).
9. Навигация подтверждена.
10. Вызов глобальных `afterEach` хуков.
11. Выполняется обновление DOM.
12. Вызов коллбэков, переданных в `next` в `beforeRouteEnter` хуке с созданными экземплярами.