13. Роутинг и навигация
Роутинг (Routing) и навигация — ключевые механизмы построения современных SAPUI5/Fiori приложений, позволяющие управлять переходами между экранами, состояниями и параметрами URL.
Основные понятия
- Роутер (Router) — компонент, отвечающий за сопоставление URL и отображаемых представлений (View).
- Route — правило, описывающее, какой View показывать при определённом URL.
- Target — конкретный View или фрагмент, который будет отображён.
- Pattern — шаблон URL, по которому определяется, какой маршрут активировать.
Зачем нужен роутинг?
- Позволяет создавать SPA (Single Page Application) с "чистыми" URL.
- Обеспечивает возможность закладок и прямых ссылок на определённые экраны.
- Упрощает управление историей переходов (Back/Forward).
- Позволяет передавать параметры между экранами.
Конфигурация роутинга (Freestyle)
Роутинг обычно настраивается в файле manifest.json:
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "my.app.view",
"controlId": "app",
"controlAggregation": "pages",
"bypassed": {
"target": "notFound"
},
"async": true
},
"routes": [
{
"pattern": "",
"name": "home",
"target": "home"
},
{
"pattern": "detail/{id}",
"name": "detail",
"target": "detail"
}
],
"targets": {
"home": {
"viewName": "Home",
"viewLevel": 1
},
"detail": {
"viewName": "Detail",
"viewLevel": 2
},
"notFound": {
"viewName": "NotFound"
}
}
}
Навигация между экранами (Freestyle)
Для перехода между экранами используется роутер:
this.getOwnerComponent().getRouter().navTo("detail", {
id: 42
});
"detail"— имя маршрута.{ id: 42 }— параметры, которые попадут в URL и будут доступны в целевом контроллере.
Обработка параметров маршрута
В контроллере целевого View:
onInit: function() {
this.getOwnerComponent().getRouter()
.getRoute("detail")
.attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function(oEvent) {
var sId = oEvent.getParameter("arguments").id;
// Используйте sId для загрузки данных
}
Навигация назад
Для возврата на предыдущий экран:
onNavBack: function() {
var oHistory = sap.ui.core.routing.History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getOwnerComponent().getRouter().navTo("home", {}, true);
}
}
Ленивая загрузка (Lazy Loading)
Для оптимизации производительности рекомендуется использовать асинхронную загрузку View ("async": true в конфиге роутинга).
Примеры роутинга и навигации в Fiori Elements
В Fiori Elements роутинг и навигация реализованы на уровне фреймворка и тесно связаны с OData и аннотациями. Обычно URL содержит binding context, отражающий ключевые поля сущности.
Пример URL для Object Page:
/webapp/index.html#/SalesOrderSet('500000001')
Пример конфигурации в manifest.json (Fiori Elements):
"routing": {
"routes": [
{
"pattern": ":?query:",
"name": "list",
"target": "list"
},
{
"pattern": "SalesOrderSet({key})",
"name": "object",
"target": "object"
}
],
"targets": {
"list": {
"type": "Component",
"id": "list",
"name": "sap.suite.ui.generic.template.ListReport"
},
"object": {
"type": "Component",
"id": "object",
"name": "sap.suite.ui.generic.template.ObjectPage"
}
}
}
Навигация из ListReport в ObjectPage происходит автоматически при выборе строки, и URL содержит ключевые поля выбранной сущности.
Пример кастомной навигации в контроллере Extension:
onNavigateToObjectPage: function(oEvent) {
var oContext = oEvent.getSource().getBindingContext();
var sPath = oContext.getPath(); // например, "/SalesOrderSet('500000001')"
this.getOwnerComponent().getRouter().navTo("object", {
key: encodeURIComponent(sPath.match(/\('(.+)'\)/)[1])
});
}
Best Practice: Использование binding context из OData в роутинге и в Freestyle-приложениях
Хорошей практикой является использование binding context из OData в качестве аргументов роутинга. Это позволяет:
- Делать URL максимально прозрачными и отражающими бизнес-сущности (например, ключи объектов).
- Обеспечивать прямую связь между отображаемыми данными и URL.
- Упрощать закладки и обмен ссылками между пользователями.
Реализация:
- При навигации передавайте ключевые поля (или binding path) в параметры маршрута.
- При открытии страницы делайте bind страницы к этому контексту:
// Навигация
this.getOwnerComponent().getRouter().navTo("object", {
key: oContext.getProperty("ID")
});
// В onInit целевого контроллера
onInit: function() {
this.getOwnerComponent().getRouter()
.getRoute("object")
.attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function(oEvent) {
var sKey = oEvent.getParameter("arguments").key;
var sPath = "/EntitySet('" + sKey + "')";
this.getView().bindElement({
path: sPath
});
}
Преимущества:
- В строке браузера отображаются те же ключи, что и в интерфейсе.
- Легко реализовать deep linking и восстановление состояния.
- Повышается прозрачность и предсказуемость навигации.
Советы и лучшие практики
- Используйте осмысленные имена маршрутов и шаблоны URL.
- Не перегружайте один View множеством маршрутов — лучше разбивать на отдельные экраны.
- Для вложенной навигации (например, в Master-Detail) используйте
viewLevelдля анимаций и правильной истории переходов. - Обрабатывайте несуществующие маршруты через
bypassedи отдельный NotFound View. - Для сложных сценариев используйте события роутера (
attachRouteMatched,attachBypassedи др.). - В Fiori Elements используйте стандартные шаблоны и аннотации для навигации между сущностями.