Vue Router предоставляет мощный механизм управления навигацией между различными компонентами приложения на Vue.js. Часто возникает необходимость программно инициировать переход между маршрутами, например, после выполнения определённого действия пользователя или в ответ на асинхронное событие. Для таких сценариев используется навигация из actions.
В Vue 3 с использованием Composition API доступ к маршрутизатору
осуществляется через функцию useRouter. В Vuex или Pinia
actions не имеют прямого доступа к экземпляру маршрутизатора, поэтому
его нужно передавать явно или импортировать.
Пример передачи роутера в action:
// store.js
export const useStore = defineStore('main', {
actions: {
async login(userData, router) {
const response = await api.login(userData);
if (response.success) {
router.push({ name: 'dashboard' });
}
}
}
});
В этом примере роутер передается как аргумент в action, что позволяет управлять переходами внутри логики хранилища.
Vue Router поддерживает несколько способов программного перехода:
push – добавляет новый маршрут в
историю браузера.replace – заменяет текущий
маршрут, не создавая новую запись в истории.go – перемещает пользователя на
указанное количество шагов в истории.Примеры использования в action:
actions: {
navigateToProfile(router, userId) {
router.push({ name: 'profile', params: { id: userId } });
},
navigateToHome(router) {
router.replace({ path: '/' });
}
}
Ключевые моменты:
push подходит для обычных переходов, когда важно
сохранить возможность возвращения назад.replace используется для переходов после действий, где
возврат к предыдущему маршруту нежелателен (например, после успешного
логина).Программный переход позволяет передавать дополнительные данные через query-параметры или hash. Это особенно полезно для фильтрации данных или сохранения состояния страницы.
actions: {
filterProducts(router, category) {
router.push({
name: 'products',
query: { category }
});
},
scrollToSection(router, sectionId) {
router.push({
path: '/home',
hash: `#${sectionId}`
});
}
}
Особенности работы с query и hash:
route.query.scrollBehavior в роутере.Методы push и replace возвращают промис,
что позволяет обрабатывать возможные ошибки, например, при попытке
перехода на текущий маршрут:
actions: {
safeNavigate(router, route) {
router.push(route).catch(err => {
if (err.name !== 'NavigationDuplicated') {
console.error('Ошибка навигации:', err);
}
});
}
}
Это предотвращает выброс ненужных ошибок при повторном переходе на тот же маршрут.
Часто необходимо выполнить навигацию после успешного запроса к API.
Использование async/await в actions обеспечивает
последовательное выполнение:
actions: {
async submitForm(router, formData) {
try {
const result = await api.submit(formData);
if (result.success) {
router.push({ name: 'thankYou' });
}
} catch (error) {
console.error('Ошибка при отправке формы:', error);
}
}
}
Таким образом, переход осуществляется только после подтверждения успешного выполнения действия.
В Pinia actions полностью поддерживают работу с Vue Router, и подход передачи роутера аналогичен Vuex:
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
actions: {
logout(router) {
this.user = null;
router.replace({ name: 'login' });
}
}
});
Pinia позволяет хранить логику навигации в одном месте, делая код более чистым и модульным.
При использовании Composition API можно напрямую импортировать роутер
через useRouter внутри функций, вызываемых из actions:
import { useRouter } from 'vue-router';
export function useAuthActions(store) {
const router = useRouter();
async function login(userData) {
const res = await api.login(userData);
if (res.success) {
router.push({ name: 'dashboard' });
}
}
return { login };
}
Такой подход позволяет избежать передачи роутера через аргументы и упрощает взаимодействие между store и компонентами.