Навигация по областям страницы
В рабочем интерфейсе вокруг содержимого стоит оболочка: меню, профиль,
шапка. При переходе по ссылке внутри оболочки достаточно заменить одну
область — содержимое, а оболочку оставить на месте. Это делает
SF.RegionNavigation из ядра Framework: объект доступен сразу после
выполнения core.js, но ничего не делает, пока страница его не включит.
Ответ области готовит сервер продукта; Framework описывает только контракт.
Включение
Страница включает навигацию один раз, назвав область, её место на странице, заголовок запроса и метку ревизии оболочки:
<meta name="shop-shell-revision" content="2026-10-16.3">
<header>…меню и профиль…</header>
<main id="shop-content">
<h1>Заказы</h1>
…
</main>
<script>
SF.RegionNavigation.enable({
region: 'content',
root: '#shop-content',
header: 'X-Shop-Region',
revisionMeta: 'shop-shell-revision',
scope: '/admin'
});
</script>
| Настройка | Что задаёт | По умолчанию |
|---|---|---|
region |
имя области, которую просит навигация; сервер возвращает его в ответе | content |
root |
селектор или сам элемент области на странице | обязательна |
header |
имя заголовка запроса, которым страница просит область; значение заголовка — имя области | обязательна |
revisionMeta |
имя <meta>, в content которого лежит ревизия оболочки |
обязательна |
scope |
начало пути: навигация берёт только адреса, путь которых с него начинается | / |
onFullLoad |
функция (url, reason), которая вызывается вместо полной загрузки страницы |
— |
Без root, header или revisionMeta вызов выбрасывает TypeError.
Повторный enable() заменяет прежние настройки. Имя заголовка и метки
выбирает продукт; Framework не знает имён продуктов.
Какие ссылки берёт навигация
Навигация берёт обычный щелчок левой кнопкой по a[href] без клавиш
Ctrl, Cmd, Shift и Alt, если адрес:
- на том же источнике, что страница;
- лежит под
scope; - не ведёт к якорю на этой же странице.
Браузеру остаются ссылки с download, ссылки с target, отличным от
_self, ссылки внутри элемента с атрибутом data-full-load и щелчки,
которые уже обработал другой код (preventDefault()).
<a href="/admin/orders">Заказы</a> <!-- меняется область -->
<a href="/admin/reports" data-full-load>Отчёты</a> <!-- загружается вся страница -->
Запрос и ответ сервера
Навигация отправляет GET по адресу ссылки с куками этого сайта и двумя
заголовками: заголовком из header со значением region и
Accept: application/json. Сервер отвечает статусом 200 и JSON с типом
application/json:
{
"region": "content",
"html": "<h1>Заказы</h1><shop-order-list></shop-order-list>",
"title": "Заказы — Магазин",
"assets": [
{"key": "shop.orders", "href": "/assets/orders.css", "kind": "css"},
{"key": "shop.orders", "href": "/assets/orders.js", "kind": "javascript"}
],
"shell_revision": "2026-10-16.3",
"url": "/admin/orders?status=new"
}
| Поле | Что означает |
|---|---|
region |
имя области; должно совпасть с region из настроек |
html |
разметка области, строкой |
title |
заголовок документа после перехода; необязательно |
assets |
ресурсы области: href, kind (css или javascript) и необязательный key, который попадает в атрибут data-sf-asset; необязательно |
shell_revision |
ревизия оболочки, строкой; должна совпасть с ревизией в <meta> страницы |
url |
адрес, который попадает в историю; если его нет или он на другом источнике, в историю попадает адрес ссылки |
Без заголовка области тот же адрес отдаёт обычную HTML-страницу. Ответы
HTML и JSON живут по одному адресу, поэтому сервер ставит
Vary с именем заголовка области, чтобы кеш их не смешал. Перенаправление на
вход остаётся перенаправлением: навигация увидит его и загрузит страницу
целиком.
Когда страница загружается целиком
Навигация никогда не оставляет на экране наполовину заменённую страницу. Страница загружается целиком, если:
- ревизия оболочки в ответе отличается от ревизии на странице — значит, изменилась сама оболочка;
- статус ответа не 200, ответ пришёл через перенаправление или его тип не
application/json; - в ответе другая область,
htmlне строка, нетshell_revisionилиassetsне список; - ответ не пришёл за 15 секунд или запрос завершился сбоем;
- на странице нет элемента области или
<meta>с ревизией.
Перед полной загрузкой на document приходит событие sf-region-fallback
с detail: {url, reason}. Если задан onFullLoad, вызывается он, и
страница остаётся на месте.
Что происходит при переходе
- На
documentприходит отменяемое событиеsf-region-navigateсdetail: {url, region}.preventDefault()отменяет переход. - Незавершённый прежний запрос прерывается; применяется только последний.
- Если ответ задерживается дольше 150 мс, область получает
aria-busyи скелетонdata-sf-region-loading; оболочка не меняется (Скелетон области страницы). - Таблицы стилей области загружаются до замены, поэтому новое содержимое не показывается без оформления.
- Адрес попадает в историю, содержимое области заменяется — в переходе
View Transitions, если браузер его поддерживает и человек не просил
уменьшить движение. Элементы, которые ушли, отключаются и освобождают свои
маршруты, слушатели и таймеры. Заголовок документа берётся из
title. - Скрипты области загружаются после замены, и её элементы оживают на месте.
- Прокрутка уходит в начало, фокус — на первый
h1области (он получаетtabindex="-1", если своего нет). - На
documentприходит событиеsf-region-loadсdetail: {url, region, title}.
Ресурсы загружаются один раз
Ресурсы области — это assets из ответа и теги <link rel="stylesheet"> и
<script src> внутри html. Навигация вынимает их из разметки и загружает
сама: каждый адрес один раз за жизнь страницы. Ресурс, который уже подключён
на странице, повторно не запрашивается; две области с одним файлом ждут один
и тот же запрос. Встроенный <script> без src из разметки области
удаляется и не выполняется: код области приходит файлами.
Если файл не загрузился, область всё равно показывается, а компонент, которому файл был нужен, сам сообщает своё состояние.
«Назад» и «Вперёд»
Каждая запись истории, в том числе та, с которой страница открылась,
помечена навигацией. «Назад» и «Вперёд» снова просят область по адресу записи
и заменяют её тем же путём; «Назад» возвращает прокрутку, которая была у
записи. Навигация берёт восстановление прокрутки на себя
(history.scrollRestoration = 'manual').
Управление из кода
| Член | Что делает |
|---|---|
enable(options) |
включает навигацию; возвращает true |
navigate(url) |
переходит по адресу так же, как по ссылке; возвращает обещание true, если область заменена, и false, если переход отменён или страница загружается целиком. Без включённой навигации просто открывает адрес |
disable() |
снимает обработчики щелчков и истории и прерывает незавершённый запрос |
enabled |
true, пока навигация включена |
| Событие | detail |
Когда |
|---|---|---|
sf-region-navigate |
{url, region} |
перед запросом; отменяемое |
sf-region-load |
{url, region, title} |
область заменена, скрипты загружены, фокус на заголовке |
sf-region-fallback |
{url, reason} |
перед полной загрузкой страницы |
Все три события приходят на document.
Смотрите также
- Фрагменты интерфейса — что стоит в области и как фрагменты освобождают ресурсы.
- Типы значений маршрутов —
navigation: переход в области как значение маршрута. - Скелетон области страницы — как выглядит область во время перехода.
- Как работает Loader — когда доступен каждый
SF.*. - Фрагмент интерфейса (
simai.interface-fragment) — требованияregion-navigationиfull-load-fallback.