SAPUI5中如何将属性值传递给init方法?

Ruf*_*ufi 2 javascript sapui5

假设我有一堂课

sap.ui.core.Control.extend("sap.my.MyButton", {
    metadata: {
        properties: {                
            "isButtonWithMenu": {
                type: "boolean",
                defaultValue: true
            }
        }
    }
},

init: function () {
    if (this.getIsButtonWithMenu()) {
         this.myButton = this._createMenuButton();
    } else {
         this.myButton = this._createNormalButton();
    }
    var baseBox = new sap.m.FlexBox();
    baseBox.addItem(this.myButton);
    this.setLayout(baseBox);
}
Run Code Online (Sandbox Code Playgroud)

现在我想将 的值传递isButtonWithMenu到我的init方法中,并执行以下操作:

var myButton = new sap.my.MyButton({isButtonWithMenu: false});
Run Code Online (Sandbox Code Playgroud)

但这不起作用,这意味着我没有在类中获得传递的值。但是,当我更改它时defaultValue,它确实有效,那么,这里出了什么问题以及我如何实现我的目标?

Ser*_*scu 5

您的问题是由ManagedObject's constructor 中的代码引起的。此类是任何控件的超类(ManagedObject <-- Element <-- Control)。如果您查看代码,您会发现发生了以下步骤:

  • 构建一个空的属性包(实际上使用您的默认值)。
  • init调用该控件的方法。
  • 属性包mSettings应用于您的控件。该属性包是您(或 XML 视图解析器)在控件构造函数中传递的属性包。

这是UI5 的设计行为。因为该init函数应该使控件处于初始化状态,并且只有此后属性(传递给构造函数)才会应用于您的控件。这确保了您重新定义的任何 setter 总是在控件初始化后被调用(嗯,至少除了您在初始化代码中调用它们的情况)。

为了解决这个问题,我可以考虑两个选择:

  • 使用 0 延迟调用技巧(有关说明,请参阅设置为 0 毫秒时 setTimeout 会做什么?)。基本上您可以执行以下操作:jQuery.sap.delayedCall(0, this, function() { this.myButton = ... })确保设置已应用于您的控件。
  • 定义一个 constructor 控制方法。大致如下:
 sap.ui.core.Control.extend("sap.my.MyButton", {

    metadata: { /* same as before */},

    constructor: function () {
        sap.ui.core.Control.apply(this, arguments);

        // the init function was already called by this point
        // also the settings should have been applied

        if (this.getIsButtonWithMenu()) {
             this.myButton = this._createMenuButton();
        } else {
             this.myButton = this._createNormalButton();
        }
        var baseBox = new sap.m.FlexBox();
        baseBox.addItem(this.myButton);
        this.setLayout(baseBox);

    }
})
Run Code Online (Sandbox Code Playgroud)

您还可以将代码放在超级构造函数调用之前(从 OOP 角度来看并不正确),但是您不能使用 getter,而应该查看mSettings构造函数参数(第二个参数)内部。