Использование навигационных цепочек может быть полезным для сложных сайтов, поскольку они дают пользователям четкое визуальное представление об иерархии сайта и более простой подход для пользователя, чтобы отслеживать свои шаги, улучшая их опыт и вовлеченность, а также снижая показатели отказов для наших сайтов. .
В этом посте мы рассмотрим пошаговый процесс создания интуитивно понятного компонента Breadcrumbs с помощью Nuxt и пользовательского интерфейса Storefront в нашем подробном руководстве.
Важность хлебных крошек в веб-навигации
Тропа хлебных крошек отображает текущее местоположение в веб-приложении в контексте иерархии приложения и позволяет пользователям легко возвращаться к предыдущим страницам или уровням. Он предлагает альтернативное визуальное представление для облегчения навигации, часто горизонтальную последовательность текстовых ссылок, разделенных символом >
, чтобы указать уровень вложенности текста, следующего за ним.
Вы можете просматривать хлебные крошки как иерархию каталогов файлов, где корень отображается первым, а ссылка на текущую страницу отображается последней.
Существует три типа хлебных крошек: на основе местоположения, атрибута и пути. В этом посте будет обсуждаться реализация компонента Breadcrumbs на основе пути для нашего приложения Nuxt с использованием его механизма маршрутизации и пользовательского интерфейса Storefront для визуального отображения.
Примечание. Для приложения Vue с установленным Vue Router вы можете легко повторно использовать обсуждаемый в этом посте код с небольшими изменениями.
Предпосылки
Было бы полезно, если бы у вас было настроено и готово к работе приложение Nuxt с помощью следующей команды:
npx nuxi init breadcrumbs-demo
Какой breadcrumbs-demo
является названием нашего демо-приложения кода. Вы можете изменить имя на любое по своему усмотрению.
Далее давайте добавим в наш проект пользовательский интерфейс Storefront, установив его пакет и модуль TailwindCSS для Nuxt с помощью следующей команды:
yarn add -D @nuxtjs/tailwindcss @storefront-ui/vue
Вы должны следовать Инструкциям по пользовательскому интерфейсу Storefront, чтобы настроить TailwindCSS и пользовательский интерфейс Storefront вместе в продукте Nuxt. После этого мы готовы к нашему уроку!
Понимание файловой системы маршрутизации
Nuxt использует Vue Router и файловую систему для создания маршрутов приложения из файлов в каталоге /pages
. Например, если у вас есть следующая файловая структура:
\page |--index.vue |--\products |-----index.vue |-----details.vue
За кулисами движок Nuxt автоматически построит следующие маршруты:
\
в качестве домашней страницы сpages\index.vue
в качестве компонента представления. Его имя будетindex
, такое же, как имя файла.\products
сpages\products\index.vue
и имеетproducts
в качестве имени.\products\details
для представленияpages\products\details
с именемproducts-details
, посколькуdetails
вложено вproducts
.
Вы можете просмотреть маршруты, используя метод getRoutes()
экземпляра маршрутизатора. Вы также можете назвать маршрут динамическим, используя синтаксис []
, например [sku].vue
. В этом случае Nuxt сгенерирует динамический путь как /:sku()
, где :sku()
является шаблоном Regex, который Vue Router будет использовать для сопоставления и извлечения целевых параметров в поле sku
, когда это уместно.
Большой. Теперь мы понимаем, как работает система маршрутизации в Nuxt. Мы можем построить наш механизм хлебных крошек, разбивая URL на крошки.
Создание компонуемого файла useBreadcrumbs
Чтобы построить наши хлебные крошки, мы создаем компонуемый объект useBreadcrumbs()
, в котором выполняем следующие действия:
- Следите за изменениями маршрута, особенно в свойствах
name
,path
иmeta
, а не всего объектаroute
. - Инициализируйте значение по умолчанию для нашего массива
breadcrumbs
в качестве маршрута Home. - Немедленно активируйте наблюдатель, чтобы у нас также были подсчитаны хлебные крошки при начальной загрузке или обновлении страницы.
- Передайте
breadcrumbs
в качестве возвращаемого значения для компонуемого. - Мы запускаем наблюдателей только тогда, когда текущий маршрут не находится на главной странице.
Основной код для useBreadcrumbs()
выглядит следующим образом:
export const useBreadcrumbs = () => { const route = useRoute() const HOMEPAGE = { name: 'Home', path: '/' }; const breadcrumbs:Ref<Array<{ name: string; path: string; }>> = ref([ HOMEPAGE ]) watch(() => ({ path: route.path, name: route.name, meta: route.meta, matched: route.matched, }), (route) => { if (route.path === '/') return; //TODO - generate the breadcrumbs }, { immediate: true, }) return { breadcrumbs } }
Далее мы реализуем, как вычислять хлебные крошки из текущего маршрута, включая динамические и вложенные способы.
Обработка динамических и вложенных маршрутов
Для создания хлебных крошек страницы всегда лучше, чтобы текущий маршрут знал, кто его родитель. Однако в Vue Router и Nuxt, к сожалению, такой возможности нет. Вместо этого мы можем построить пути хлебных крошек, рекурсивно разрезая текущий путь хлебных крошек по последнему индексу символа /
.
Возьмем, к примеру, наш путь /products/about/keychain
. Мы разобьем его на следующие пути: "/products/about/keychain"
, "/products/about"
, "/products"
и ""
. Каждый путь — это хлебная крошка, которую нам нужно отобразить. И чтобы получить отображаемое имя для этих хлебных крошек, нам нужно сделать следующее:
- Получите список доступных маршрутов из
router
экземпляраuseRouter()
. - Мы найдем соответствующий маршрут для каждого пути хлебных крошек.
- Наше условие остановки — это когда сокращенный путь — Домашняя страница.
Наш код для getBreadcrumbs()
выглядит следующим образом:
function getBreadcrumbs(currPath: string): any[] { //1. When we reach the root, return the array with the Home route if (currPath === '') return [ HOMEPAGE ]; //2. Continue building the breadcrumb for the parent's path const parentRoutes = getBreadcrumbs(currPath.slice(0, currPath.lastIndexOf('/'))); //3. Get the matching route object //TODO //4. Return the merged array with the new matching route return [ ...parentRoutes, { path: currPath, //TODO name: currPath, } ] }
В настоящее время мы возвращаем currPath
как path
и name
для хлебных крошек. Тем не менее, мы должны реализовать способ обнаружения соответствующего маршрута на основе сгенерированных конфигураций маршрутов из Nuxt, включая динамические маршруты и динамические вложенные маршруты. Давайте сделаем это дальше.
Соответствие шаблону маршрута
При работе с соответствующими путями маршрутов возникает множество сценариев, связанных с динамическими маршрутами, которые нам необходимо обработать, в том числе:
- Динамические маршруты, такие как
/products/:id()
- Динамический маршрут и статический маршрут для одного родителя, например
/products/:id()
(pages/produts/[id].vue
) и/products/about
(pages/products/about.vue
) - Динамический маршрут, вложенный в другой динамический маршрут, например
/products/:id()/:field()
Самый простой подход — разбить маршрут и текущий путь на части с помощью разделителя /
. Затем мы повторяем элементы и сравниваем один к одному, чтобы увидеть, является ли это одним и тем же значением или начинается ли подпуть с :
, как показано в следующем коде для isMathPatternPath
:
const isMathPatternPath = (pathA: string, pathB: string) => { const partsA = pathA.split('/'); const partsB = pathB.split('/'); if (partsA.length !== partsB.length) return false; const isMatch = partsA.every((part: string, i: number) => { return part === partsB[i] || part.startsWith(':'); }) return isMatch; }
Затем мы используем isMathPatternPath
в нашей функции getBreadcrumbs()
на currPath
и в результате получаем массив совпадающих маршрутов со следующими предположениями:
- Если есть статический маршрут, а динамический маршрут находится на одном родительском объекте, они будут совпадать для обоих.
- Статические маршруты всегда будут отображаться перед динамическими маршрутами в таком массиве сопоставленных маршрутов (буквы появляются перед такими символами, как «:»).
- Совпадающий массив содержит более одного результата для статического маршрута с динамическим одноуровневым маршрутом. В этом случае мы возьмем точное совпадение, используя сравнение
===
. В противном случае массив должен содержать один результат.
И таким образом, наша реализация для getBreadcrumbs()
будет такой:
function getBreadcrumbs(currPath: string): any[] { //1. When we reach the root, return the array with Home route if (currPath === '') return [ HOMEPAGE ]; //2. Continue building the breadcrumb for the parent's path const parentRoutes = getBreadcrumbs(currPath.slice(0, currPath.lastIndexOf('/'))); //3. Get the matching route object const founds = routes.filter(r => isMathPatternPath(r.path, currPath)); const matchRoute = founds.length > 1 ? founds.find(r => r.path === currPath) : founds[0]; //4. Return the merged array with the new matching route return [ ...parentRoutes, { path: currPath, name: matchRoute?.meta?.breadcrumb || matchRoute?.name || matchRoute?.path || currPath, } ] }
На основе matchRoute
мы будем использовать поле meta.breadcrumb
, чтобы получить желаемое имя для отображения, или его имя, путь или currPath
в качестве резервного значения.
И мы можем обновить наш компонуемый useBreadcrumbs()
следующим кодом:
export const useBreadcrumbs = () => { //... watch(() => ({ path: route.path, name: route.name, meta: route.meta, matched: route.matched, }), (route) => { if (route.path === '/') return; breadcrumbs.value = getBreadcrumbs(route.path); }, { immediate: true, }) //... }
После этого наш useBreadcrumbs()
готов к использованию. Давайте покажем это!
Интеграция с компонентом пользовательского интерфейса
Мы скопируем код Хлебных крошек Storefront UI со значком «Домой» и вставим в наш components/Breadcrumbs.vue
.
В разделе script setup
мы изменим breadcrumbs
на props следующим образом:
const props = defineProps({ breadcrumbs: { type: Array, required: true, }, });
В примере кода каждая навигационная цепочка имеет name
и link
. Следовательно, нам нужно найти item.link
и заменить их на item.path
в разделе template
. Кроме того, мы хотим отображать SfLink
как NuxtLink
, чтобы избежать полной перезагрузки страницы, добавляя :tag="NuxtLink"
к каждому SfLink
, появляющемуся в template
, и следующее к разделу script
:
import { resolveComponent } from 'vue'; const NuxtLink = resolveComponent('NuxtLink');
Большой. Наш компонент Breadcrumbs
готов.
Теперь в /layouts/default.vue
мы получим breadcrumbs
из компонуемого useBreadcrumbs()
и передадим его компоненту Breadcrumbs
для рендеринга, как показано ниже:
<template> <Breadcrumbs class="mt-4 ml-4" :breadcrumbs="breadcrumbs"/> <div class="h-px m-4 bg-neutral-200 divider"></div> <slot /> </template> <script setup> import { useBreadcrumbs } from '../composables/useBreadcrumbs'; const { breadcrumbs } = useBreadcrumbs(); </script>
Наконец, убедитесь, что в вашем app.vue
есть следующий код:
<template> <NuxtLayout> <NuxtPage /> </NuxtLayout> </template>
И это все, что нужно. Когда мы переходим на страницу, приложение отображает соответствующие хлебные крошки:
Как вы заметили, текущие хлебные крошки используют имя по умолчанию, определенное в сопоставленном маршруте, которое только иногда можно прочитать. В нашей реализации мы использовали route.meta?.breadcrumb
в качестве имени хлебной крошки. Чтобы определить meta.breadcrumb
, мы будем использовать встроенный метод Nuxt definePageMeta
, как в следующем примере:
<script setup> /**pages/products/index.vue */ definePageMeta({ breadcrumb: 'Products Gallery', }) </script>
Во время сборки Nuxt объединит метаданные нужной страницы с meta
маршрута, и у нас будут соответствующие хлебные крошки:
Обратите внимание, что вы не можете определить мета, следуя описанному выше подходу для динамического маршрута. Вместо этого в useBreadcrumbs
вы можете просмотреть route.params
и получить соответствующее имя из параметров и соответствующих данных, таких как название продукта.
Краткое содержание
Рабочий код вы можете найти здесь.
В этом посте мы рассмотрели, как создать механизм хлебных крошек для нашего приложения Nuxt, используя его встроенный маршрутизатор, и визуализировать их с помощью компонента хлебных крошек с помощью пользовательского интерфейса Storefront. Реализация проста и может быть не оптимальной по сравнению с такими подходами, как Regex, в более сложной системе маршрутизации с несколькими уровнями вложенных динамических и статических маршрутов. Тем не менее, это хорошая отправная точка для создания собственной системы хлебных крошек, и помните о правилах KISS!
Я надеюсь, что вы найдете этот пост полезным. Если у вас есть какие-либо вопросы или предложения, пожалуйста, оставьте комментарий ниже. Я хотел бы услышать от вас.
👉 Если хотите иногда быть со мной в курсе, подпишитесь на меня в Твиттере | Фейсбук.
👉 Узнайте больше о Vue из моей новой книги Learning Vue. Ранний выпуск уже доступен для чтения!
Понравился этот пост или нашел его полезным? Поделись 👇🏼 😉
Первоначально опубликовано на https://mayashavin.com.