Хлебные крошки через meta

В Vue Router ключ meta предоставляет возможность хранить дополнительную информацию о маршруте, которая не влияет на работу маршрутизатора напрямую, но может быть использована для различных целей: контроля доступа, отображения названий страниц или построения навигационных элементов, таких как хлебные крошки.

Структура маршрута с meta

Маршруты в Vue Router задаются объектами с полями path, component и опциональными дополнительными свойствами. Ключ meta обычно используется как объект с произвольными данными:

import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
import Team from '@/views/Team.vue';

const routes = [
  {
    path: '/',
    component: Home,
    meta: { breadcrumb: 'Главная' }
  },
  {
    path: '/about',
    component: About,
    meta: { breadcrumb: 'О компании' },
    children: [
      {
        path: 'team',
        component: Team,
        meta: { breadcrumb: 'Команда' }
      }
    ]
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

В этом примере для каждого маршрута определено свойство breadcrumb внутри meta, которое будет использоваться для отображения текущего пути в виде хлебных крошек.

Динамическая генерация хлебных крошек

Для построения хлебных крошек необходимо пройтись по массиву активных маршрутов, который хранится в router.currentRoute.value.matched. Каждый объект маршрута в этом массиве содержит meta, что позволяет извлекать название для каждой крошки.

import { computed } from 'vue';
import { useRoute } from 'vue-router';

export default {
  setup() {
    const route = useRoute();

    const breadcrumbs = computed(() => {
      return route.matched.map(r => ({
        name: r.meta.breadcrumb || r.name,
        path: r.path
      }));
    });

    return { breadcrumbs };
  }
};

Здесь breadcrumbs — это реактивный массив объектов, содержащих name и path каждой крошки. При изменении маршрута массив автоматически обновляется.

Поддержка вложенных маршрутов

При работе с вложенными маршрутами важно учитывать, что путь дочернего маршрута может быть относительным. В таких случаях для хлебных крошек рекомендуется использовать свойство path из matched, которое уже содержит полный путь:

const breadcrumbs = computed(() => {
  return route.matched.map(r => ({
    name: r.meta.breadcrumb || r.name,
    path: r.path
  }));
});

Такой подход гарантирует корректное построение ссылок даже для многоуровневых маршрутов.

Динамические параметры маршрута

Для маршрутов с параметрами (:id, :slug) следует подставлять реальные значения из route.params:

const breadcrumbs = computed(() => {
  return route.matched.map(r => {
    let path = r.path;
    Object.keys(route.params).forEach(key => {
      path = path.replace(`:${key}`, route.params[key]);
    });
    return {
      name: r.meta.breadcrumb || r.name,
      path
    };
  });
});

Таким образом, крошки автоматически подставляют конкретные идентификаторы или слаги, например: /about/team/42.

Интеграция в шаблон

Для отображения хлебных крошек можно использовать простой цикл v-for в Vue:

<template>
  <nav aria-label="breadcrumb">
    <ol class="breadcrumb">
      <li
        v-for="(crumb, index) in breadcrumbs"
        :key="crumb.path"
        :class="{ 'active': index === breadcrumbs.length - 1 }"
      >
        <router-link v-if="index !== breadcrumbs.length - 1" :to="crumb.path">
          {{ crumb.name }}
        </router-link>
        <span v-else>{{ crumb.name }}</span>
      </li>
    </ol>
  </nav>
</template>

<script setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

const breadcrumbs = computed(() => {
  return route.matched.map(r => {
    let path = r.path;
    Object.keys(route.params).forEach(key => {
      path = path.replace(`:${key}`, route.params[key]);
    });
    return {
      name: r.meta.breadcrumb || r.name,
      path
    };
  });
});
</script>

<style scoped>
.breadcrumb {
  display: flex;
  list-style: none;
  padding: 0;
}
.breadcrumb li + li::before {
  content: '/';
  padding: 0 0.5rem;
}
.breadcrumb .active {
  font-weight: bold;
}
</style>

Поддержка международных языков

Для мультиязычных приложений можно использовать meta в сочетании с функцией перевода:

meta: { breadcrumb: t('breadcrumbs.home') }

Или динамически вычислять имя крошки через функцию в meta:

meta: {
  breadcrumb: route => `Пользователь ${route.params.id}`
}

В этом случае при построении массива крошек нужно проверять, является ли breadcrumb функцией и вызывать её с текущим маршрутом:

const breadcrumbs = computed(() => {
  return route.matched.map(r => {
    let name = typeof r.meta.breadcrumb === 'function'
      ? r.meta.breadcrumb(route)
      : r.meta.breadcrumb || r.name;
    let path = r.path;
    Object.keys(route.params).forEach(key => {
      path = path.replace(`:${key}`, route.params[key]);
    });
    return { name, path };
  });
});

Вывод

Использование meta в Vue Router позволяет строить гибкие и динамичные хлебные крошки, поддерживающие вложенные маршруты, динамические параметры и мультиязычные приложения. Комбинация route.matched, route.params и meta.breadcrumb обеспечивает простое и масштабируемое решение для навигационных элементов.