如何在UI5中正确附加和分离事件处理程序
我的自定义控件的数据绑定有问题。
我的控件继承自sap.m.Input
,并使用特殊的值helper对其进行扩展。我的新控件的一个新属性是Value Help对话框的一个简单标题。这绑定到I18N模型。
当我现在以正常形式使用我的控件时,一切都可以正常工作。标题已正确绑定,并显示该模型中绑定的I18N属性的值。如果我将我的控件用作sap.ui.table
控件列中的模板,它只显示Title属性的默认值。数据绑定似乎不起作用。但仍在处理继承的属性(如值)。
这里是简化的控件代码:
sap.ui.define([
"sap/ui/core/Control",
"sap/m/Input",
], function(Control, Input) {
"use strict";
return Input.extend("DvpClsSuggestInput", {
"metadata": {
"properties": {
// Title of Value-Help Dialog
"vhTitle": {
type: "string",
defaultValue: "Title"
}
}
},
init: function() {
Input.prototype.init.apply(this, arguments);
this.setShowValueHelp(true);
this.attachValueHelpRequest(this.onValueHelpRequest.bind(this));
},
onValueHelpRequest: function(oEvent) {
var lvTitle = this.getVhTitle();
alert(lvTitle);
},
});
});
});
sap.ui.table.Table
中的用法(不起作用,显示Title属性的默认值):
<table:Column>
<m:Label text="{i18gn>HausWaehrung}" />
<table:template>
<dvp:MyInput
value="{ path: 'Inv>Hwaer', type: 'sap.ui.model.type.String' }"
vhTitle="{i18n>Currency}" />
</table:template>
</table:column>
有效的用法:
<VBox>
<dvp:MyInput
value="{ path: 'Cls>/Currency', type: 'sap.ui.model.type.String' }"
vhTitle="{i18n>Currency}" />
</VBox>
同样,针对value属性的绑定在两种情况下都有效。问题只存在于我自己的属性vhTitle
。欢迎任何想法。
解决方案
将事件处理程序附加到ManagedObject
的事件时,请勿使用.bind
。分离事件处理程序也是如此。UI5在这些情况下有自己的记录机制来传递侦听器对象。
示例%1
Attaching/detachingvalueHelpRequest
-处理程序使用相应的API并将值传递到参数列表,如API参考中所述:
myInput.attachValueHelpRequest(/*obj?,*/this.onValueHelpRequest, this); // No .bind!
myInput.detachValueHelpRequest(this.onValueHelpRequest, this); // Same references
示例2
将事件处理程序附加到控件实例化,如ManagedObject
's API reference中所述(所有控件均为ManagedObjects):
new MyInput({
// ...,
valueHelpRequest: [/*obj?,*/this.onValueHelpRequest, this]
});
有效名称和值范围:
- [.]
- 对于事件,要么接受函数(事件处理程序),要么是长度为2的数组,其中第一个元素是函数,第二个元素是要调用方法的对象;或者是长度为3的数组,其中第一个元素是任意负载对象,第二个是函数,第三个是调用[.]方法的对象。
示例3(面向控件开发人员)
但是,在控件定义中,可以完全省略侦听器,因为如果没有传递侦听器对象,则事件提供程序本身(即您的控件实例)在默认情况下将成为侦听器。
this.attachValueHelpRequest(this.onValueHelpRequest); // the control instance will be used as the context in that event handler
API reference中也有说明:
如果未指定<;oListener>;,则在事件提供程序的上下文中调用处理程序函数。
在UI5中使用Function.prototype.bind
的缺点
在函数上调用
.bind
时,创建了一个完整的新函数!const myFn = function() {}; myFn === myFn.bind(); // returns: false
表示如果使用
.bind
传递处理程序,则该处理程序将变为永远不可分离,因为detachEvent
等待与调用attachEvent
时相同的函数引用和侦听器对象引用。更糟糕的是,使用
.bind
创建的函数不允许您更改之前传递的thisArg(this
),即使EventProvider
tries tocall
之后使用不同的thisArg来更改函数。ECMAScript specification(请参阅注释2)中描述了此限制,也说明了问题中描述的问题的原因。ManagedObject
克隆聚合绑定的template
控件时,不能覆盖监听器!
相关文章