Meta-поля маршрутов и доступ по ролям

↑ 5.1 Vue Router · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Декларативная конфигурация доступа к маршрутам и типизация meta.

Объяснение

Маршрут может нести произвольные данные в meta.

// Типизация
declare module "vue-router" {
  interface RouteMeta { requiresAuth?: boolean; roles?: string[]; title?: string; layout?: "default" | "blank"; keepAlive?: boolean }
}
 
const routes: RouteRecordRaw[] = [
  { path: "/login", component: LoginPage, meta: { layout: "blank", title: "Вход" } },
  {
    path: "/admin", component: AdminLayout, meta: { requiresAuth: true, roles: ["admin"] },
    children: [{ path: "users", component: UsersPage, meta: { title: "Пользователи" } }],
  },
];
 
// meta наследуется по вложенности: используйте matched
router.beforeEach((to) => {
  const needsAuth = to.matched.some(r => r.meta.requiresAuth);
  const roles = to.matched.flatMap(r => r.meta.roles ?? []);
  if (needsAuth && !auth.user) return { name: "login", query: { redirect: to.fullPath } };
  if (roles.length && !roles.some(r => auth.user?.roles.includes(r))) return { name: "forbidden" };
});

Применения meta:

ПолеИспользование
requiresAuth, roles, permissionsдоступ
title, breadcrumbзаголовок страницы и хлебные крошки
layoutвыбор шаблона (<component :is> в App.vue)
keepAliveкэширование страницы
transitionанимация перехода

ACL: вместо ролей лучше права (permissions): permissions: ["orders:read"]; роль → набор прав определяется на бэкенде. Меню генерируется из маршрутов (видимость по правам), кнопки — директивой v-can.

Динамические маршруты: после логина router.addRoute(...) только для доступных модулей (уменьшает бандл и раскрытие структуры).

Нюансы и подводные камни

  • meta не наследуется автоматически в to.meta (в v4 «слито» из совпавших записей, но лучше использовать matched).
  • Проверка ролей на клиенте — UX; сервер должен отклонять запросы.
  • Хардкод строк ролей размазывается по проекту: соберите в константы/перечисление.
  • Прямой заход по ссылке: пользователь ещё не загружен — дождитесь инициализации.

Практика

  1. Типизируйте RouteMeta и настройте guard по matched.
  2. Сгенерируйте меню из маршрутов с учётом прав.
  3. Добавьте layout в meta и выбирайте шаблон в App.vue.

Вопросы с ответами

Связанные темы