在视图中:
<List selectionChange="onSelectionChange">
在控制器中:
onSelectionChange : function (oEvent) {
console.log(oEvent.sId); //log 1, output "selectionChange"
MessageBox.warning(Utils.i18n("CHANGE_CONFIRM"), {
actions: [Utils.i18n("LEAVE_BTN"), MessageBox.Action.CANCEL],
onClose: function(sAction) {
console.log(oEvent.sId); //log 2, output "closed"
if(sAction === Utils.i18n("LEAVE_BTN")) {
this._showDetail(oEvent.getParameter("listItem") || oEvent.getSource(), oEvent.getSource().data("target"));
}
}.bind(this)
});
}
嗨,我可以问一下oEvent
触发onClose
时为什么会发生变化?为什么我不能将oEvent
存储在我的范围内?
答案 0 :(得分:2)
Event是一个实现Poolable的模块,这意味着事件必须实现init
和reset
,然后才能使用它相应的ObjectPool实例(&#34; oEventPool&#34;内部)重用现有的事件实例以用于下一个事件。
&#34;下一个事件&#34;,在我们的例子中,是对话框触发的"close"
事件。正如您已经观察到的那样,oEvent
突然没有ID "selectionChange"
而是"close"
。这是因为 Event 实例已重置并重新使用。由于oEvent
只是一个引用(不是副本),并且因为JS应用了Call by Object-Sharing,所以它已经改变了#34;。
ObjectPool 的API参考解释了它对事件实例所做的事情:
(ObjectPool)维护给定类型的自由对象列表。如果调用sap.ui.base.ObjectPool.prototype.borrowObject,则从池中获取现有的空闲对象,并在此对象上调用
init
方法。当不再需要时,应通过调用#returnObject将任何借来的对象返回到池中。在那个时间点,在对象上调用
reset
方法,并将对象添加到自由对象列表中。
目前,( oEvent )对象被视为"no longer needed" when its handler is called。因此,该对象已在onSelectionChange
之后立即重置,并在触发onClose
之前再次初始化。
UI5这样做是为了不必创建和销毁多个 Event 实例来提高性能。这是借鉴Object Pool Design Pattern(也是often used in game development)的做法。
那么,作为应用程序开发人员,它对我们意味着什么?只是不要依赖闭包内的事件对象。相反,将对象的原始值分配给单独的变量,以便我们以后可以使用它们。 E.g:
onSelectionChange: function(oEvent) {
const eventId = oEvent.getId(); // === "selectionChange"
MessageBox.warning(/*...*/, {
onClose: function() {
/* oEvent.getId() === suddenly "close" but
eventId === still "selectionChange" */
},
});
},