在全屏应用中实现导航
学习目标
为全屏应用实现视图与导航。
实现导航
在完成路由配置之后,我们接下来看看如何使用路由器(router)以及已配置的路由(route)。
实现 Carrier 视图
我们全屏应用的起点是 Carrier 视图。
在本视频中,我们来看看如何实现这个 Carrier 视图:
视频:本节含 SAP 官方视频(视频 ID
1_ermhch6a),需在 learning.sap.com 在线观看。
sap.m.Page 拥有一个名为 content 的聚合。该 content 聚合的类型为 sap.ui.core.Control。在上面所示的示例中,一个 sap.m.Table 控件(1)被添加到 content 聚合中。该表格绑定到实体 CarrierCollection。对于该集合中的每个实体,都会创建一个 ColumnListItem(2)类型的对象并将其添加到表格中。
实现 Flights 明细视图
Flights 视图通过 sap.m.ObjectHeader 控件显示航班的主数据。这些数据来自视图级别设置的相对数据绑定,正如我们在之前的控制器中所看到的。

Flights 视图的实现显示了所选承运人的详细信息,以及以表格形式显示的该所选承运人的航班列表。为了提供导航回 Carrier 视图的功能,我们向 page 对象添加值为 true 的属性 showNavButton。
为了处理返回导航,我们为 navButtonPress 事件(1)分配一个事件处理函数。该事件处理函数在 flights 控制器中实现。
在 Flights 页面上实现返回按钮
为了启用从 Flights 视图到 Carrier 视图的返回导航,我们必须添加相应的事件处理函数。

实现一个返回组件路由器实例的函数。也可以使用 this.getOwnerComponent().getRouter()。
实现事件处理函数 onNavBack 。 该函数检查应用历史中是否存在先前的哈希值,如果存在,则通过浏览器原生的 History API 重定向到先前的哈希值。如果不存在,则使用路由器(Router)导航到路由 overview,即 carriers overview 视图。 路由器的 navTo 函数通过路由名称和一个布尔参数来调用,该布尔参数指示是否应创建浏览器历史记录条目。
true :哈希值被替换(不创建浏览器历史记录条目)
false :哈希值被设置(创建浏览器历史记录条目)
为无效的 Carrier ID 显示 NotFound 页面
正如前几课所介绍的,我们必须确保应用能够处理无效的哈希值。为了对无效哈希值做出响应,我们必须扩展 *Flights.controller.js* 中的元素绑定。

为了响应绑定操作的 change 事件,你可以附加一个事件处理函数。你可以在导航路由中不引用目标(target)而手动显示它们。很好的例子包括临时错误、切换到业务对象的编辑页面,或跳转到 "Settings" 页面。
在 _onBindingChange() 处理函数内部,我们获取路由器 Targets 辅助对象的引用,并简单地调用 display("notFound")。 与路由配置中名为 notFound 的目标相关联的视图将由路由器显示,且不会更改哈希值。 sap.m.routing.Targets 对象通过调用路由器上的 getTargets() 获取。不过,你也可以通过调用 this.getOwnerComponent().getRouter().getTargets() 或 this.getOwnerComponent().getTargets() 来获取 sap.m.routing.Targets 对象的引用。
在全屏应用中实现导航
业务示例
在下面的练习中,你将学习如何使用 SAPUI5 在全屏应用中实现导航。
注意
SAP Business Technology Platform 及其工具都是云服务。由于云软件的特性,操作步骤以及字段和按钮的命名可能与练习解答有所不同。
前提条件
你应当已完成本单元的第一个练习,以导入全屏应用。
任务 1:添加用于导航的控件
现在我们要对从 carriers 表格中选择某个承运人这一操作做出响应。因此,请为 ColumnListItem 元素的 press 事件实现一个事件处理函数。将该函数命名为 onPress。从所选项读取属性 Carrid。此外,将 ColumnListItem 元素的 type 属性设置为 Navigation。在本任务中,我们将调整 *Carrier.view.xml* 文件。
步骤
打开
*Carrier.view.xml*文件,并为ColumnListItem元素的 press 事件分配一个名为onPress的事件处理函数。将
press属性添加到ColumnListItem:
press="onPress"
将属性
type添加到ColumnListItem元素,并为该属性赋值Navigation。然后保存你的更改。将
type属性添加到ColumnListItem:
type="Navigation"
保存你的更改。现在你应该具有以下代码:

任务 2:为导航实现 Carrier 视图行为
在下面的任务中,你必须在 Carrier 视图控制器中实现 onPress 函数。onPress 函数从事件发起者读取属性 Carrid。读取该属性后,将调用路由 flights,并将承运人的 id 作为参数传递给该路由。
步骤
打开
*Carrier.controller.js*文件并移除onInit函数。打开
*Carrier.controller.js*文件。移除
onInit函数。
在 Carrier 视图的视图控制器中实现一个函数
getRouter。该函数应返回组件路由器对象的引用。使用以下代码:
getRouter: function () {
return sap.ui.core.UIComponent.getRouterFor(this);
}
向 Carrier 视图控制器的控制器实现添加一个名为
onPress的事件处理函数。该函数接受一个名为oEvent的参数。添加一个名为
onPress的函数。该函数应接受一个名为oEvent的参数。使用以下代码:
onPress: function(oEvent) {
}
从事件发起者的绑定上下文中读取属性
Carrid,并将该值存储在局部变量sCarrid中。声明一个名为
oItem的变量,并将事件源对象赋值给该变量。声明一个名为
oCtx的变量,并将事件源对象的绑定上下文赋值给该变量。声明一个变量
sCarrid。使用函数getProperty从oCtx-Object读取属性Carrid的值,并将结果赋值给变量sCarrid。你在 onPress 函数内部的实现应如下所示:
var oItem = oEvent.getSource();
var oCtx = oItem.getBindingContext();
var sCarrid = oCtx.getProperty("Carrid");
使用路由
flights导航到 Flights 视图。通过属性carrierId将sCarrid的值作为参数传递给该路由。使用路由器的navTo函数来触发导航。在变量定义之后使用以下代码:
this.getRouter().navTo("flights", {
carrid: sCarrid
}, false);
你的控制器实现应如下所示:
保存你的更改。现在你应该具有以下代码:

任务 3:为导航实现 Flights 视图行为
步骤
在 Flights 视图的视图控制器中实现一个函数
getRouter。该函数应返回组件路由器对象的引用。打开
*Flights.controller.js*文件。使用以下代码添加一个
getRouter函数(别忘了在onInit函数之后添加逗号):
getRouter: function () {
return sap.ui.core.UIComponent.getRouterFor(this);
}
实现 Flights 控制器的
onInit函数。为路由flights注册一个函数_onObjectMatched。该函数将在后续的某个步骤中实现。找到
onInit函数。创建一个名为
oRouter的变量,并为其赋值路由器引用。使用以下代码:
var oRouter = this.getRouter();
当路由
flights被匹配时注册函数_onObjectMatched。输入以下代码:
oRouter.getRoute("flights").attachMatched(this._onObjectMatched, this);
现在你应该具有以下代码:

实现函数
_onObjectMatched。该函数应从事件参数 arguments 中读取属性carrierId,并将视图绑定到所选的承运人。为change事件注册_onBindingChange函数。然后为事件dataRequested和dataReceived注册匿名事件处理函数。当事件dataRequested发生时,视图应被设置为忙碌模式;当dataReceived发生时,忙碌模式应被设置为 false。在本步骤中,创建一个带有一个调用参数oEvent的函数_onObjectMatched。然后从事件对象中检索名为arguments的参数,读取属性Carrid并将值存储在局部变量_sCarrierId中。此外,获取视图并将其赋值给局部变量oView。创建一个带有一个调用参数
oEvent的函数_onObjectMatched。在getRouter函数之后添加以下代码(别忘了添加逗号):
_onObjectMatched: function (oEvent) {
}
从事件对象中检索名为
arguments的参数。将其赋值给名为oArgs的变量。将以下代码添加到该函数中:
var oArgs = oEvent.getParameter("arguments");
从
oArgs对象读取属性carrierId,并将结果赋值给名为_sCarrierId的成员变量。添加以下代码:
this._sCarrierId = oArgs.carrid;
获取视图对象的引用,并将该引用赋值给名为
oView的局部变量。添加以下代码:
var oView = this.getView();
在视图对象上调用函数
bindElement。向该函数传递一个字面量对象。输入以下代码:
oView.bindElement({
});
将属性
path添加到该字面量对象,并使用_sCarrierId变量将绑定赋值给所选的 Carrier。将以下代码添加到
bindElement函数中:
path: "/UX_C_Carrier_TP('" + this._sCarrierId + "')",
向该字面量对象添加属性
events。将另一个字面量对象赋值给该属性。在 path 属性指定之后添加以下代码:
events: {
}
为事件
change调用_onBindingChange函数。该函数将在后续步骤中实现。将以下代码添加到
events定义中:
change: this._onBindingChange.bind(this),
为事件
dataRequested添加一个函数,并以将视图设置为忙碌的方式实现该函数。在
change事件指定之后添加以下代码:
dataRequested: function () {
oView.setBusy(true);
},
为事件
dataReceived添加一个函数,并以将视图设置为非忙碌的方式实现该函数。在
dataRequested事件指定之后添加以下代码:
dataReceived: function () {
oView.setBusy(false);
}
现在你应该具有以下代码:

向控制器实现添加一个函数
_onBindingChange。从视图获取元素绑定。如果元素绑定没有绑定的上下文,则应显示NotFound视图。获取路由器目标辅助对象的引用并调用display("notFound")。在
_onObjectMatched函数实现之后输入以下代码:
_onBindingChange: function () {
var oElementBinding;
oElementBinding = this.getView().getElementBinding();
// No data for the binding
if (oElementBinding && !oElementBinding.getBoundContext()) {
this.getRouter().getTargets().display("notFound");
}
},
向控制器实现添加一个函数
onNavBack。如果先前的哈希值为 undefined,则使用路由器的navTo函数并传入 overview 路由。然后保存你的更改。在
_onBindingChange函数实现之后添加以下代码:
onNavBack: function () {
var oHistory, sPreviousHash;
oHistory = sap.ui.core.routing.History.getInstance();
sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getRouter().navTo("overview", true /*no history*/);
}
}
保存你的所有更改。
任务 4:测试你的应用
请注意,由于我们不是在真实的 SAP Fiori 环境中测试应用,如果你使用 Dev Tools 调试应用,控制台会出现错误。请忽略任何有关资源预加载的消息。
步骤
测试你的应用。选择一个承运人以查看相应的航班。应显示 Flights 视图。

按照前面练习中所示的方式执行此步骤。
尝试导航到不存在路由的 URL。应显示 NotFound 视图。

在浏览器的 URL 字段中,将末尾的承运人 id 替换为不存在的值(例如 XX),然后按 Enter 键(在键盘上)。
应显示 Not Found 视图。