Как использовать динамические маршруты в Vue?
Динамические маршруты в Vue позволяют обрабатывать URL-пути с переменными сегментами. Это особенно полезно, когда ты хочешь отобразить разные данные на основе параметров маршрута, например, при переходе на страницу профиля пользователя (/user/123) или детальной информации о продукте (/product/456). Vue Router предоставляет встроенные инструменты для настройки таких маршрутов и получения параметров внутри компонентов.
Объявление динамического маршрута
Для создания динамического маршрута в routes.js или в конфигурации маршрутизатора используется двоеточие : перед именем параметра:
import UserProfile from './views/UserProfile.vue';
const routes = \[
{
path: '/user/:id',
name: 'UserProfile',
component: UserProfile
}
\];
Здесь :id — это параметр маршрута. Он может принимать любое значение: /user/1, /user/42, /user/john.
Получение параметров в компоненте
Вариант 1: Через useRoute() (Composition API)
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
const userId = route.params.id;
</script>
Вариант 2: Через this.$route.params (Options API)
export default {
mounted() {
const userId = this.$route.params.id;
// можно загрузить данные пользователя по ID
}
};
Особенности реактивности
Параметры маршрута реактивны: при переходе с /user/1 на /user/2 тот же компонент может остаться активным, но params обновятся. Чтобы правильно отреагировать на такие изменения, можно использовать watch.
Пример:
watch(() => route.params.id, (newId, oldId) => {
fetchUserById(newId);
});
Повторное использование компонента
Когда ты переходишь от /user/1 к /user/2, Vue по умолчанию не пересоздаёт компонент, а обновляет параметры. Поэтому если ты загружаешь данные в mounted(), то они не обновятся. Решения:
-
Использовать watch на route.params.
-
Переместить загрузку в beforeRouteUpdate.
-
Или разрешить повторное создание компонента с помощью ключа:
<router-view :key="$route.fullPath" />
Передача параметров как props
Vue Router может передать параметры как props в компонент. Это делает компонент более предсказуемым и независимым от глобального объекта this.$route.
{
path: '/user/:id',
component: UserProfile,
props: true
}
Внутри UserProfile.vue:
export default {
props: \['id'\],
mounted() {
console.log('ID пользователя:', this.id);
}
};
Также можно использовать функцию, чтобы преобразовать параметры:
{
path: '/user/:id',
component: UserProfile,
props: route => ({ id: Number(route.params.id) })
}
Несколько параметров в маршруте
Можно использовать несколько параметров:
{
path: '/category/:categoryId/product/:productId',
component: ProductDetail
}
Путь /category/5/product/123 будет иметь params = { categoryId: '5', productId: '123' }.
Динамические маршруты и beforeRouteEnter
Иногда нужно подгрузить данные до отображения компонента:
beforeRouteEnter(to, from, next) {
fetchUser(to.params.id).then(user => {
next(vm => {
vm.user = user;
});
});
}
С ограничениями (RegExp)
Можно ограничить значение параметра:
{
path: '/user/:id(\\\\d+)',
component: UserProfile
}
Теперь id должен быть числом (/user/abc не сработает, /user/123 — сработает).
Использование с вложенными маршрутами
Динамические параметры можно использовать и во вложенных маршрутах:
{
path: '/users/:userId',
component: UserLayout,
children: \[
{
path: 'posts',
component: UserPosts
},
{
path: 'settings',
component: UserSettings
}
\]
}
Путь /users/42/posts отобразит компонент UserPosts с userId = 42.
Обработка несуществующих ID
Когда пользователь вводит несуществующий ID в URL, компонент может получить undefined при попытке загрузки данных. Рекомендуется обрабатывать это:
watch(() => route.params.id, async (id) => {
const user = await fetchUser(id);
if (!user) {
router.push('/not-found');
}
});
Программная навигация с параметрами
Можно перейти к маршруту с параметрами:
router.push({ name: 'UserProfile', params: { id: 42 } });
Если маршрут задан с name, такой способ удобен и надёжен.
Обработка повторного перехода
Если перейти к тому же маршруту с теми же параметрами, Vue Router по умолчанию проигнорирует переход. Чтобы обновить данные вручную, можно слушать клик или использовать key для <router-view>.
Ошибки при отсутствии props: true
Если ты хочешь использовать параметры как props, но не включил props: true, то в props они не попадут. Компоненту придётся использовать useRoute() или this.$route, что делает компонент зависимым от маршрутизатора. Лучше передавать явно через props.
Взаимодействие с сервером
Динамические параметры часто используются для подгрузки данных с бэкенда. Например, при заходе на /product/123 ты делаешь GET /api/products/123. При изменении параметра маршрута (например, переход на /product/124) ты снова делаешь запрос.
Тестирование динамических маршрутов
Для unit-тестов можно подставить параметры вручную:
const route = useRoute();
route.params.id = '123';
Или смонтировать компонент с mock-объектом:
mount(UserProfile, {
global: {
mocks: {
$route: {
params: { id: '123' }
}
}
}
});