breadcrumb хлебные крошки —— Навигация
Хлебные крошки — это индикатор пути «где я и как я сюда попал»: Главная / Настройки / Безопасность / Двухфакторная аутентификация. Они легче меню — передают только иерархический путь, не неся основную навигацию; слабее индикатора шагов — не выражают последовательность процесса, а выражают отношение вложенности. Когда уровней много, путь становится длинным, и сворачивание — его основной алгоритм.
Когда использовать
Заголовок раздела «Когда использовать»- Реализация
<LhBreadcrumb>/<LhBreadcrumbItem>на всех концах: иерархические пути в административных системах, пути категорий на сайтах документации, категории товаров. - Сценарии, где нужно показать текущую позицию и предоставить вход для постепенного возврата.
- Не следует использовать: основная навигация (используйте
menu); пошаговые процессы (используйтеsteps); переключение однорангового содержимого (используйтеtabs); путь из одного уровня (это не хлебные крошки, а заголовок страницы).
import { getBreadcrumbItemClassNames, getEllipsisBeforeIndex, getCollapsedHiddenIndexes, getBreadcrumbItemAria,} from '@lh-ui/share/core/breadcrumb'import type { LhBreadcrumbItemState, LhBreadcrumbCollapseState } from '@lh-ui/share/core/breadcrumb'Замысел
Заголовок раздела «Замысел»При сворачивании сохраняется первый элемент: правило getEllipsisBeforeIndex — «первый элемент + многоточие + последние maxItems-1 элементов». Первый элемент сохраняется всегда — это якорь «вернуться на самый верхний уровень» (обычно «Главная»), и его скрытие лишит пользователя возможности вернуться к корню. Этот компромисс так же важен, как и «сохранение последнего элемента» (текущая позиция).
Перед каким элементом вставляется многоточие: возвращается индекс первого видимого элемента после многоточия (total - (maxItems - 1)); UI-слой вставляет элемент-многоточие перед этой позицией. Без сворачивания возвращается -1 — обратите внимание: -1 это сигнальное значение «без сворачивания», а не валидный индекс.
При maxItems < 2 сворачивания нет: нужно показать хотя бы первый элемент + один последующий, иначе сворачивание лишено смысла. При maxItems: 1 и меньше возвращается -1 — это защитное проектирование, чтобы при неверной настройке хлебные крошки не свернулись в одно только многоточие.
Связь getCollapsedHiddenIndexes с индексом многоточия: скрываются элементы «между первым элементом и многоточием», то есть полуоткрытый интервал [1, ellipsisIndex) — первый элемент (индекс 0) и элементы после позиции многоточия сохраняются. Функции работают в паре: сначала берётся позиция многоточия, затем вычисляется множество скрытых.
aria-current=“page” у последнего элемента: последний элемент — «текущая страница», и aria-current="page" — стандартная семантика WAI-ARIA; скринридер озвучивает «текущая страница», что точнее текстовой подсказки. Для не последних элементов aria-атрибуты не выводятся (семантика ссылки несёт нативный <a>).
Таблица функций
Заголовок раздела «Таблица функций»| Функция | Сигнатура | Возврат | Назначение |
|---|---|---|---|
getBreadcrumbItemClassNames |
(state: LhBreadcrumbItemState) => string[] |
классы | состояние ссылки + последний элемент |
getEllipsisBeforeIndex |
(state: LhBreadcrumbCollapseState) => number |
индекс / -1 | позиция многоточия |
getCollapsedHiddenIndexes |
(state: LhBreadcrumbCollapseState) => number[] |
множество скрытых индексов | скрытые элементы при сворачивании |
getBreadcrumbItemAria |
(isLast: boolean) => LhAriaAttrs |
aria-пакет | aria-current для последнего элемента |
Определения типов
Заголовок раздела «Определения типов»export interface LhBreadcrumbItemState { isLast: boolean // последний ли элемент (текущая страница) isLink: boolean // рендерится ли как ссылка (передан to и не последний)}
export interface LhBreadcrumbCollapseState { total: number // общее количество элементов maxItems: number // максимальное число видимых элементов (включая многоточие); меньше 2 — без сворачивания}Доступность
Заголовок раздела «Доступность»getBreadcrumbItemAria(true) // { 'aria-current': 'page' }getBreadcrumbItemAria(false) // {}- aria-current=“page” только у последнего элемента: промежуточные элементы — кликабельные ссылки, им не нужна текущая метка. Скринридер при входе на страницу озвучит: «Главная, ссылка / Настройки, ссылка / Безопасность, ссылка / Двухфакторная аутентификация, текущая страница» — путь и позиция передаются целиком за один раз.
- Нативный
<a>вместо перехода через JS: если промежуточный элемент — реальная ссылка, используйте<a href="...">— поддерживается открытие в новой вкладке средней кнопкой, копирование ссылки правой кнопкой, работа без JS. Клиентский роутинг реализуется перехватом клика в UI-слое (@click.prevent), href сохраняется. Комментарий кgetBreadcrumbItemAriaобъясняет это: при наличии ссылки роль берёт на себя нативныйa, функции выводить ничего не нужно. - Доступность кнопки-многоточия: свёрнутое многоточие обычно кликабельно и разворачивает полный путь. Это элемент управления, ему нужен
aria-label="Развернуть полный путь"(либоaria-expandedдля выражения состояния развёрнутости) — иначе это безымянная кнопка. - Обёртка nav + aria-label: хлебным крошкам рекомендуется
<nav aria-label="Хлебные крошки">— на странице может быть несколько nav (основная навигация, постраничная), aria-label их различает. - Разделители декоративны: разделители
/или»— чистая декорация:aria-hiddenили реализация через CSS-псевдоэлемент, чтобы скринридер не зачитывал каждый слеш.
Примеры использования
Заголовок раздела «Примеры использования»import { getEllipsisBeforeIndex, getCollapsedHiddenIndexes, getBreadcrumbItemAria,} from '@lh-ui/share/core/breadcrumb'
getEllipsisBeforeIndex({ total: 6, maxItems: 4 }) // 3 (многоточие вставляется перед индексом 3)getEllipsisBeforeIndex({ total: 4, maxItems: 4 }) // -1 (всего <= maxItems, без сворачивания)getEllipsisBeforeIndex({ total: 6, maxItems: 1 }) // -1 (maxItems < 2, без сворачивания)getEllipsisBeforeIndex({ total: 6, maxItems: 2 }) // 5 (первый элемент + последние 1)
getCollapsedHiddenIndexes({ total: 6, maxItems: 4 }) // [1, 2] (между первым элементом и многоточием)getCollapsedHiddenIndexes({ total: 4, maxItems: 4 }) // [] (без сворачивания)// UI-слой: свёрнутый рендер (состояние развёрнутости управляется локальным state)const expanded = ref(false)const items = ['Главная', 'Система', 'Настройки', 'Безопасность', 'Аккаунт', 'Двухфакторная аутентификация']const ellipsisIndex = computed(() => getEllipsisBeforeIndex({ total: items.value.length, maxItems: props.maxItems ?? 4 }),)const hidden = computed(() => expanded.value ? [] : getCollapsedHiddenIndexes({ total: items.value.length, maxItems: props.maxItems ?? 4 }),)<!-- Vue3 --><template> <nav aria-label="Хлебные крошки"> <LhBreadcrumb :max-items="4"> <LhBreadcrumbItem to="/">Главная</LhBreadcrumbItem> <LhBreadcrumbItem to="/system">Система</LhBreadcrumbItem> <LhBreadcrumbItem to="/system/security">Безопасность</LhBreadcrumbItem> <LhBreadcrumbItem>Двухфакторная аутентификация</LhBreadcrumbItem> </LhBreadcrumb> </nav></template>// React: данные пути обычно выводятся из таблицы роутов (useMatches / собственный route meta),// а не объявляются поэлементно вручную — отображение хлебных крошек на роуты// является бизнес-соглашением// uniapp: <navigator> — нативный компонент перехода; на стороне мини-программ нет// семантики <nav>, использование view + aria-label не работает — это приемлемо// (экосистема скринридеров в мини-программах иная), главное — сохранить структуру DOMСтили и токены
Заголовок раздела «Стили и токены»| Класс | Семантика |
|---|---|
.lh-breadcrumb |
контейнер (inline-flex) |
.lh-breadcrumb__item |
один элемент |
.lh-breadcrumb__item--link |
состояние ссылки (изменение цвета при hover) |
.lh-breadcrumb__item--last |
последний элемент (текущая страница, жирный или основной цвет) |
.lh-breadcrumb__separator |
разделитель (обычно CSS-псевдоэлемент) |
.lh-breadcrumb__ellipsis |
многоточие (кликабельное, разворачивает) |
Цвет текста --lh-text-regular, цвет ссылки при hover --lh-primary-color, последний элемент --lh-text-primary; размер шрифта --lh-font-size-base.
Замечания
Заголовок раздела «Замечания»maxItemsвключает многоточие:maxItems: 4фактически показывает «первый элемент + многоточие + последние 3 элемента» = 5 элементов, а видимых текстовых элементов будет 4. Настраивайте по количеству видимых текстовых элементов.- Динамичность сворачивания: длина пути меняется с глубиной навигации (
totalвgetEllipsisBeforeIndexдинамический), аmaxItemsфиксирован — вручную определять момент сворачивания не нужно, функция обрабатывает это автоматически. - Взаимодействие разворачивания многоточия: два распространённых подхода — ① клик по многоточию разворачивает всё на месте (переключение состояния
expanded); ② клик открывает popover со скрытыми элементами. Первый проще, второй экономит место; выбирайте по глубине пути. - Источник данных пути: хлебные крошки обычно выводятся из таблицы роутов, а не пишутся вручную — в meta каждого роута прописывается
title, а на уровне компонента агрегируются meta предков текущего пути. core отвечает только за алгоритм рендеринга, интеграция с роутингом — задача UI-слоя. - Последний элемент не рендерится ссылкой: указание текущей страницы на саму себя лишено смысла (и
isLink: false). Обратите внимание: класс--linkвgetBreadcrumbItemClassNamesуправляется isLink, и у последнего элемента его естественно нет. - Сокращение слишком длинных заголовков: при избыточной длине заголовка одного уровня используется CSS
text-overflow: ellipsis(стили UI-слоя); это другое «сокращение», нежели сворачивание пути — сворачивание экономит число уровней, а CSS — ширину одного уровня. - Не используйте хлебные крошки как основную навигацию: это вспомогательный индикатор позиции, главный вход остаётся за меню. На мобильных при нехватке места хлебные крошки часто опускают или оставляют только кнопку «Назад».
@lh-ui/share/core/breadcrumb → getEllipsisBeforeIndex( )(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue