问题
In view:
<List selectionChange="onSelectionChange">
In controller:
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)
});
}
Hi, may I ask why oEvent
changed when onClose
is triggered? Why can't I store oEvent
in my scope?
回答1:
Event is a module that implements Poolable, meaning that Event has to implement init
and reset
which will then be leveraged by its corresponding ObjectPool instance ("oEventPool" internally) to reuse the existing Event instance for the next event.
The "next event", in our case, is the "close"
event which was fired by the dialog. As you could already observe, oEvent
suddenly doesn't have the ID "selectionChange"
but "close"
. This is because the Event instance was reset and reused again. And since oEvent
is just a reference (not a copy), and because JS applies Call by Object-Sharing, it's "changed".
The API Reference of ObjectPool explains what it's doing with the Event instance:
(ObjectPool) maintains a list of free objects of the given type. If sap.ui.base.ObjectPool.prototype.borrowObject is called, an existing free object is taken from the pool and the init method is called on this object.
When no longer needed, any borrowed object should be returned to the pool by calling #returnObject. At that point in time, the reset method is called on the object and the object is added to the list of free objects.
Currently, the (oEvent) object is considered "no longer needed" when its handler is called. So the object is already reset right after onSelectionChange
, and initialized again right before onClose
is triggered.
UI5 does this so that it doesn't have to create and destroy multiple Event instances to improve performance. This is a practice borrowed from the Object Pool Design Pattern (which is also often used in game development).
So, what does it mean for us as application developers? Just don't rely on the event object that is inside a closure. Instead, assign primitive values from the object to separate variables so that we can use them later. E.g.:
onSelectionChange: function(oEvent) {
const eventId = oEvent.getId(); // === "selectionChange"
MessageBox.warning(/*...*/, {
onClose: function() {
/* oEvent.getId() === suddenly "close" but
eventId === still "selectionChange" 👍 */
},
});
},
来源:https://stackoverflow.com/questions/47452986/event-parameter-overwritten-after-change-event