Сопоставление динамических маршрутов с параметрами
Очень часто нам придется сопоставлять маршруты с заданным шаблоном с одним и тем же компонентом. Например, у нас может быть компонент 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
, поэтому он поддерживает множество продвинутых шаблонов сопоставления, таких как опциональные динамические сегменты и регулярные выражения. Пожалуйста, ознакомьтесь с документацией по продвинутому сопоставлению, чтобы изучить их подробнее.