В Vue Router объект meta предназначен для хранения
произвольных данных маршрута, которые могут использоваться на этапе
навигации или внутри компонентов для управления доступом, отображением
или поведением маршрута. Одним из ключевых сценариев применения
meta является реализация ролей и разрешений пользователей,
что позволяет гибко управлять доступом к различным частям
приложения.
metaКаждый маршрут может содержать объект meta, в котором
можно хранить массив разрешённых ролей или другие данные, необходимые
для контроля доступа. Например:
const routes = [
{
path: '/admin',
component: AdminDashboard,
meta: {
requiresAuth: true,
roles: ['admin', 'superuser']
}
},
{
path: '/profile',
component: UserProfile,
meta: {
requiresAuth: true,
roles: ['user', 'admin', 'superuser']
}
},
{
path: '/login',
component: LoginPage,
meta: {
requiresAuth: false
}
}
];
Ключевые моменты:
requiresAuth указывает, что маршрут доступен только
авторизованным пользователям.roles содержит массив ролей, которые имеют доступ к
маршруту.meta доступен как в глобальных навигационных
охранниках, так и в локальных компонентах через
this.$route.meta.Для контроля доступа используется глобальный навигационный охранник
beforeEach. В нём можно проверять авторизацию пользователя
и наличие соответствующей роли:
router.beforeEach((to, from, next) => {
const user = getCurrentUser(); // Получение текущего пользователя
const requiresAuth = to.meta.requiresAuth;
const allowedRoles = to.meta.roles || [];
if (requiresAuth && !user) {
next('/login');
} else if (allowedRoles.length && !allowedRoles.includes(user.role)) {
next('/unauthorized');
} else {
next();
}
});
Разбор логики:
requiresAuth) и
пользователь не вошёл, выполняется редирект на страницу логина.roles),
проверяется, есть ли роль пользователя в этом списке. Если нет,
выполняется редирект на страницу с ошибкой доступа.metameta не наследуется автоматически в Vue Router. Для
вложенных маршрутов можно реализовать проверку, проходя по всему
маршруту и проверяя каждый уровень:
router.beforeEach((to, from, next) => {
const user = getCurrentUser();
const matchedRoutes = to.matched; // Массив всех маршрутов, совпавших с адресом
const requiresAuth = matchedRoutes.some(r => r.meta.requiresAuth);
const allowedRoles = matchedRoutes
.filter(r => r.meta.roles)
.map(r => r.meta.roles)
.flat();
if (requiresAuth && !user) {
next('/login');
} else if (allowedRoles.length && !allowedRoles.includes(user.role)) {
next('/unauthorized');
} else {
next();
}
});
Особенности:
to.matched содержит массив всех маршрутов, от
родительского до конечного дочернего.flat() объединяет все массивы ролей в
один.meta внутри компонентовВ компоненте можно использовать this.$route.meta для
динамического отображения элементов интерфейса в зависимости от роли
пользователя:
<template>
<div>
<button v-if="canEdit">Редактировать</button>
<p v-if="!canView">Доступ ограничен</p>
</div>
</template>
<script>
export default {
computed: {
canEdit() {
const roles = this.$route.meta.roles || [];
return roles.includes(this.$store.state.user.role);
},
canView() {
return this.canEdit || this.$route.meta.requiresAuth === false;
}
}
}
</script>
Преимущества:
В некоторых приложениях роли могут определять доступность маршрутов, и маршруты могут добавляться динамически после авторизации:
const dynamicRoutes = [
{
path: '/reports',
component: ReportsPage,
meta: { requiresAuth: true, roles: ['manager', 'admin'] }
}
];
if (user.isAuthenticated) {
dynamicRoutes.forEach(route => router.addRoute(route));
}
router.addRoute позволяет регистрировать маршруты после
инициализации приложения.meta.roles только для проверки доступа.
Для других целей (например, хлебные крошки или заголовки страниц) лучше
заводить отдельные поля.to.matched.Роли и разрешения через meta обеспечивают гибкость и
централизованный контроль доступа, позволяя эффективно управлять
безопасностью интерфейса и навигацией в приложениях на Vue.