说明
在这一步中,我们将扩展重用概念,并在组件级调用对话框。
在第16步中,我们创建了一个对话框片段,让它可以跨视图或整个应用程序重用。但是我们把检索对话框实例,打开和关闭它的逻辑分别放在了HelloPanel视图的控制器中。坚持这种方法需要将代码复制并粘贴到我们需要的对话框的每个视图的控制器上。这将导致我们一直在避免的不必要的代码冗余。
在这一步中,我们实现了这个问题的解决方案:我们扩展了重用概念,并在组件级调用了对话框。
预览
现在这个对话框以组件的方式打开
代码
你可以在演练-第19步查看和下载所有文件。
webapp/Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/model/json/JSONModel",
"./controller/HelloDialog"
], function (UIComponent, JSONModel, HelloDialog) {
"use strict";
return UIComponent.extend("sap.ui.demo.walkthrough.Component", {
metadata : {
manifest : "json"
},
init : function () {
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// set data model
var oData = {
recipient : {
name : "World"
}
};
var oModel = new JSONModel(oData);
this.setModel(oModel);
// set dialog
this._helloDialog = new HelloDialog(this.getRootControl());
},
exit : function() {
this._helloDialog.destroy();
delete this._helloDialog;
},
openHelloDialog : function () {
this._helloDialog.open();
}
});
});
对话框实例化被重构为一个新的helper对象,该对象存储在组件的私有属性中。对于helper对象的实例化,我们必须传递视图实例给添加的对话框(请参阅下面helper对象HelloDialog.js实现中的addDependent方法调用)
我们想要将重用对话框连接到应用的根视图的生命周期中,所以我们将根视图的实例传递给构造函数。可以通过调用组件的getRootControl方法来检索它。
注意
正如manifest.json文件中的参数rootView中定义的,我们的根视图是sap.ui.demo.walkthrough.view.App。可以在运行时通过访问rootControl聚合从组件中检索根视图。
为了能够从其他控制器打开对话框,我们实现了一个重用函数openHelloDialog,它调用helper对象的open方法。通过这样做,我们还可以从应用程序编码中分离重用对话框的实现细节。
到目前为止,我们向组件添加了新的属性 _helloDialog,并为其分配了一个helloDialog对象的实例。我们希望确保在组件销毁时释放为这个helper对象分配的内存。否则,我们的应用程序可能导致内存泄漏。
为此,我们使用exit hook。SAPUI5框架在销毁组件时调用指定的exit函数。我们调用HelloDialog的销毁函数来清理helper类并结束它的生命周期。然而,实例本身仍然存在于浏览器内存中。因此,我们通过调用delete this._helloDialog 来删除对HelloDialog实例的引用,而浏览器的垃圾回收可以清理它的内存。
注意
我们不必销毁我们创建的JSONModel实例,因为我们用setModel函数将它分配给了组件。SAPUI5框架会把它和组件一起销毁。
webapp/controller/HelloDialog.js (New)
sap.ui.define([
"sap/ui/base/ManagedObject",
"sap/ui/core/Fragment"
], function (ManagedObject, Fragment) {
"use strict";
return ManagedObject.extend("sap.ui.demo.walkthrough.controller.HelloDialog", {
constructor : function (oView) {
this._oView = oView;
},
exit : function () {
delete this._oView;
},
open : function () {
var oView = this._oView;
// create dialog lazily
if (!this.pDialog) {
var oFragmentController = {
onCloseDialog : function () {
oView.byId("helloDialog").close();
}
};
// load asynchronous XML fragment
this.pDialog = Fragment.load({
id: oView.getId(),
name: "sap.ui.demo.walkthrough.view.HelloDialog",
controller: oFragmentController
}).then(function (oDialog) {
// connect dialog to the root view of this component (models, lifecycle)
oView.addDependent(oDialog);
return oDialog;
});
}
this.pDialog.then(function(oDialog) {
oDialog.open();
});
}
});
});
HelloDialog重用对象的实现扩展了一个sap.ui.base.ManagedObject对象来继承SAPUI5的一些核心功能。
我们的open方法是从HelloPanel控制器重构的,并像前面的步骤一样实例化我们的对话片段。
注意
我们不将控制器作为第三个参数传递给Fragment函数。加载一个本地helper对象oFragmentContoller,它包含了片段所需的事件处理函数onCloseDialog。
open方法现在包含了我们的对话框实例化。第一次调用open方法时,对话框被实例化。该方法的oView参数用于将当前视图连接到对话框。稍后,我们将在控制器中调用该对象的open方法。
onCloseDialog事件触发器被简单地从HelloPanel控制器移到重用对象。
我们还添加了一个exit函数,就像我们在组件中做的那样,当对象被销毁时,它将被自动调用。为了释放helper对象中所有已分配的内存,我们删除保留视图引用的属性。视图本身将被组件销毁,所以我们不需要对此进行注意。
webapp/controller/HelloPanel.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast"
], function (Controller, MessageToast) {
"use strict";
return Controller.extend("sap.ui.demo.walkthrough.controller.HelloPanel", {
onShowHello : function () {
// read msg from i18n model
var oBundle = this.getView().getModel("i18n").getResourceBundle();
var sRecipient = this.getView().getModel().getProperty("/recipient/name");
var sMsg = oBundle.getText("helloMsg", [sRecipient]);
// show message
MessageToast.show(sMsg);
},
onOpenDialog : function () {
this.getOwnerComponent().openHelloDialog();
}
});
});
onOpenDialog方法现在通过调用helper方法getOwnerComponent来访问它的组件。
当调用重用对象的open方法时,我们会通过当前视图将其连接到对话框。
webapp/view/App.view.xml
<mvc:View
controllerName="sap.ui.demo.walkthrough.controller.App"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true">
<Shell>
<App class="myAppDemoWT">
<pages>
<Page title="{i18n>homePageTitle}">
<headerContent>
<Button
icon="sap-icon://hello-world"
press=".onOpenDialog"/>
</headerContent>
<content>
<mvc:XMLView viewName="sap.ui.demo.walkthrough.view.HelloPanel"/>
</content>
</Page>
</pages>
</App>
</Shell>
</mvc:View>
我们在应用视图的头部区域添加了一个按钮来显示hello world对话框的重用。当按下按钮时,对话框将像我们之前在面板中创建的按钮一样打开。
webapp/controller/App.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("sap.ui.demo.walkthrough.controller.App", {
onOpenDialog : function () {
this.getOwnerComponent().openHelloDialog();
}
});
});
我们也将onOpenDialog方法添加到应用程序控制器中,这样对话框就会打开并引用当前视图。
约定
将在多个控制器中使用的所有资产放在单独的模块中。
章节
- 第1步:你好世界
- 第2步:引导
- 第3步:控件
- 第4步:XML视图
- 第5步:控制器
- 第6步:模块
- 第7步:JSON模型
- 第8步:可翻译的文本
- 第9步:组件配置
- 第10步:应用程序描述符
- 第11步:页面和面板
- 第12步:Shell控件作为容器
- 第13步:外边距和内边距
- 第14步:自定义CSS和主题颜色
- 第15步:嵌套视图
- 第16步:对话框和片段
- 第17步:片段回调
- 第18步:图标
- 第19步:重用对话框
- 第20步:聚合绑定
- 第21步:数据类型
- 第22步:表达式绑定
- 第23步:自定义格式器
- 第24步:过滤
- 第25步:排序和分组
- 第26步:远程OData服务
- 第27步:模拟服务器配置
- 第28步:使用QUnit进行单元测试
- 第29步:与OPA的集成测试
- 第30步:调试工具
- 第31步:路由和导航
- 第32步:路由与参数
- 第33步:路由回溯和历史
- 第34步:自定义控件
- 第35步:响应性
- 第36步:设备适应
- 第37步:内容密度
- 第38步:可访问性