Сопоставление динамических маршрутов с параметрами
Очень часто нам придется сопоставлять маршруты с заданным шаблоном с одним и тем же компонентом. Например, у нас может быть компонент User, который должен отображаться для всех пользователей, но с разными ID пользователей. Во Vue Router мы можем использовать динамический сегмент в маршруте, чтобы достичь этого, Этот сегмент называется параметром (param):
import User from './User.vue'
// маршруты передаются в `createRouter`.
const routes = [
// динамические сегменты начинаются с двоеточия
{ path: '/users/:id', component: User },
]Теперь URL-адреса типа /users/johnny и /users/jolyne будут сопоставляться с одним и тем же маршрутом.
Параметр обозначается двоеточием :. Когда маршрут найден, значение его параметров будет раскрываться как route.params в каждом компоненте. Таким образом, мы можем вывести ID текущего пользователя, обновив шаблон User на следующий:
<template>
<div>
<!-- The current route is accessible as $route in the template -->
User {{ $route.params.id }}
</div>
</template>В одном маршруте может быть несколько параметров, которые будут сопоставлены с соответствующими полями в route.params. Примеры:
| шаблон | сопоставленный путь | route.params |
|---|---|---|
| /users/:username | /users/eduardo | { username: 'eduardo' } |
| /users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
Помимо route.params, объект route также предоставляет другую полезную информацию, такую как route.query (если есть query в URL), route.hash и так далее. Вы можете ознакомиться с полными деталями в справочнике по API.
Рабочую демонстрацию этого примера можно найти здесь.
Реагирование на изменение параметров
Следует отметить, что при использовании маршрутов с параметрами, когда пользователь переходит с /users/johnny на /users/jolyne, будет использоваться тот же экземпляр компонента. Поскольку оба маршрута отображают один и тот же компонент, это более эффективно, чем уничтожение старого экземпляра и создание нового. Однако это также означает, что хуки жизненного цикла компонента не будут вызваны.
Для реагирования на изменения параметров в том же компоненте, вы можете просто следить за любым свойством объекта route, в данном случае за route.params:
<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(
() => route.params.id,
(newId, oldId) => {
// обработка изменения параметров маршрута...
}
)
</script><script>
export default {
created() {
this.$watch(
() => this.$route.params.id,
(newId, oldId) => {
// обработка изменения параметров маршрута...
}
)
},
}
</script>Или воспользуйтесь хуком навигации beforeRouteUpdate, который также позволяет вам отменить навигацию:
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
// ...
onBeforeRouteUpdate(async (to, from) => {
// обработка изменения параметров маршрута...
userData.value = await fetchUser(to.params.id)
})
</script><script>
export default {
async beforeRouteUpdate(to, from) {
// обработка изменения параметров маршрута...
this.userData = await fetchUser(to.params.id)
},
// ...
}
</script>Страница ошибки 404 / отслеживание ненайденных маршрутов
Обычные параметры будут соответствовать только символам между фрагментами URL, разделенными символом /. Если вы хотите сопоставить любые символы, вы можете использовать пользовательское регулярное выражение для параметра, добавив его в скобках сразу после параметра:
const routes = [
// будет сопоставляться всем маршрутам и будет помещено в `route.params.pathMatch`.
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
// будет сопоставляться всему, что начинается с `/user-`, и будет помещено в `route.params.afterUser`.
{ path: '/user-:afterUser(.*)', component: UserGeneric },
]В данном конкретном случае мы используем пользовательское регулярное выражение, заключенное в круглые скобки, и помечаем параметр pathMatch как опционально повторяемый. Это позволяет нам при необходимости перейти прямо к этому маршруту, разбив path на массив:
router.push({
name: 'NotFound',
// сохранить текущий путь и удалить первый символ, чтобы целевой URL не начинался с `//`.
params: { pathMatch: route.path.substring(1).split('/') },
// сохраняем существующий запрос и хэш, если таковой имеется
query: route.query,
hash: route.hash,
})Подробнее см. в разделе повторяющиеся параметры.
Если вы используете History mode, обязательно следуйте инструкциям по правильной настройке вашего сервера.
Продвинутые возможности сопоставления
Vue Router использует свой собственный синтаксис сопоставления путей, вдохновленный синтаксисом, используемым в express, поэтому он поддерживает множество продвинутых шаблонов сопоставления, таких как опциональные динамические сегменты и регулярные выражения. Пожалуйста, ознакомьтесь с документацией по продвинутому сопоставлению, чтобы изучить их подробнее.
