В Vue Router переходы между маршрутами управляются
методами $router.push, $router.replace и
навигацией через <router-link>. В процессе разработки
часто возникает ситуация, когда одно и то же действие вызывает повторный
переход к текущему маршруту или к маршруту с теми же параметрами. Такие
дублирующие переходы могут привести к предупреждениям в
консоли, нежелательным перерендерингам компонентов или логическим
ошибкам в приложении.
Vue Router учитывает идентичность маршрутов по сочетанию:
path — путь маршрута;params — параметры маршрута;query — параметры запроса.Если новое обращение к маршруту полностью совпадает с текущим маршрутом по этим трём критериям, Vue Router распознаёт переход как дублирующий и в версии 3.x и выше выбрасывает NavigationDuplicated.
Пример:
this.$router.push({ name: 'user', params: { id: 1 } })
.catch(err => {
if (err.name !== 'NavigationDuplicated') throw err;
});
Здесь, если текущий маршрут уже user с параметром
id: 1, переход не выполнится, а ошибка будет поймана в
блоке catch.
Для безопасного управления переходами рекомендуется перехватывать ошибку:
function safePush(location) {
return router.push(location).catch(err => {
if (err.name === 'NavigationDuplicated') {
return router.currentRoute;
}
throw err;
});
}
Дополнительно можно заранее проверять текущий маршрут:
if (router.currentRoute.fullPath !== targetRoute.fullPath) {
router.push(targetRoute);
}
<router-link>Даже при использовании компонентов <router-link>
возможно возникновение дублирующих переходов, если:
to указывает на текущий маршрут;Для минимизации этого эффекта можно использовать директиву
exact:
<router-link :to="{ name: 'home' }" exact>Главная</router-link>
exact предотвращает активное выделение ссылки при
совпадении только части маршрута, что косвенно снижает вероятность
дублирующих переходов.В Vue Router можно создать глобальный навигационный guard, чтобы централизованно обрабатывать повторные переходы:
router.beforeEach((to, from, next) => {
if (to.fullPath === from.fullPath) {
next(false); // Отмена дублирующего перехода
} else {
next();
}
});
next(false) полностью предотвращает
навигацию.При работе с параметризованными маршрутами дублирующий переход может
возникнуть даже при изменении query-параметров, если основной
path не изменился:
router.push({ name: 'search', query: { q: 'vue' } });
router.push({ name: 'search', query: { q: 'vue' } }); // NavigationDuplicated
path или query.function isSameRoute(routeA, routeB) {
return routeA.fullPath === routeB.fullPath;
}
В приложениях с ленивой загрузкой компонентов или асинхронными данными дублирующие переходы могут привести к повторным вызовам API. Чтобы избежать этого:
$router.push.catch для обработки
NavigationDuplicated.fullPath перед
переходом.exact для <router-link>
при необходимости.Эти практики обеспечивают стабильную работу навигации, предотвращают лишние перерендеринги и делают приложение более предсказуемым.