更改事件后事件参数被覆盖?

时间:2017-11-23 10:16:36

标签: sapui5

在视图中:

<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存储在我的范围内?

1 个答案:

答案 0 :(得分:2)

Event是一个实现Poolable的模块,这意味着事件必须实现initreset,然后才能使用它相应的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"  */
    },
  });
},