为什么 OpenUI5 控件的扩展原型不能一致工作?

问题描述 投票:0回答:3

我使用的是openui5。 UI 控件 Button 有一个构造函数,无法看到 Button 的原型属性,但在浏览器控制台中执行时会显示相同的内容!

 sap.m.Button.prototype.Move = function(){
  console.log('Move');
} 
var oButton = new sap.m.Button({text:"Hello"});
oButton.Move(); // throws undefined function! 

在控制台中的浏览器中执行相同的代码,它可以工作!

jsbin --> http://jsbin.com/tepum/1/edit

oop prototype javascript sapui5
3个回答
3
投票

运行代码后,我发现创建 sap.m.Button 的第一个实例会导致脚本更改 sap.m.Button 的原型。它在 JavaScript 中是有效的,但如果你问我的话,它不是很聪明。

第一次创建会导致同步请求(也不是)来获取library-parameters.json。

如果第二次运行代码,它将具有prototype.move,因为创建Button的实例不会改变Button.prototype。

Move 中的大写 M 表示构造函数,因此我建议将其更改为小写。

由于获取参数是同步的,您可以创建第一个实例,然后设置原型:

console.log("First Button creation changes Button.prototype");
var oButton = new sap.m.Button({text:"Hello"});
sap.m.Button.prototype.move = function(){
  console.log('Move');
} 
oButton.placeAt('content');
oButton.move(); // logs Move

我的猜测是,这是为了延迟加载控件,如果从未创建 Button,则永远不会为这些未使用的控件加载 json 配置文件。但它有一些缺点。

  1. 您必须先创建一个实例,然后才能设置原型。
  2. 配置文件是同步加载的,因此在创建许多控件的第一个实例时连接速度较慢会导致应用程序无响应。

更好的方法是工厂函数返回一个承诺,这样你每次都以相同的方式创建控件,并且可以异步获取配置文件。

[更新]

查看配置,它似乎是整个 gui 库的配置,所以我看不出为什么只有在创建第一个实例后才加载它的任何原因。在创建实例时更改其对象定义的库不太容易扩展,因为它是不可预测的。如果它只在第一次创建时更改原型,那么应该没问题,但看起来库的创建者不希望人们扩展它,或者他们不会使对象定义变得不可预测。如果有可用的 api 文档,那么也许可以尝试检查一下。

[更新]

扩展控件的“正确”方法似乎是使用 extend


3
投票

@HMR是正确的,扩展控件的正确方法是使用UI5托管对象提供的扩展功能,请参阅http://jsbin.com/linob/1/edit

在下面的示例中,当按照其他人提到的进行调试时,您会注意到控件在需要时是延迟加载的,您之前所做的任何更改在加载时都会丢失

    jQuery.sap.declare("my.Button");
    jQuery.sap.require("sap.m.Button");
    sap.m.Button.extend("my.Button", {
        renderer: {} 
    });

    my.Button.prototype.Move = function() {
        console.log('Move');
    };

    var oButton = new my.Button({
        text: "Hello"
    });
    oButton.placeAt('content');
    oButton.Move();

2
投票

它本身并没有隐藏原型。如果构造函数正常退出,那么您将获得该函数的原型。但是,如果构造函数实际上返回某个其他对象,那么您将获得该其他对象的原型,因此不能仅仅因为添加到 Button 原型而假设在调用 new Button() 时您将在任何对象上看到您的方法你回来吧。我确信如果您对该代码进行反混淆,您会发现您正在调用的构造函数在其末尾有一个“return new SomeOtherInstanceOfButton()”或类似的内容。

编辑:好吧,要了解 sap 代码中到底发生了什么有点困难,但是,看起来他们的代码覆盖了控件的原型以向其添加功能,例如:sap.ui.core.EnabledPropagator,以及在您实际实例化按钮之前,这些事情不会运行。因此,如果您更改代码以实例化页面上的按钮,然后添加到其原型,然后构造并调用该方法,它就可以正常工作。像这样:

http://jsbin.com/benajuko/2/edit

所以我想我的答案是,当您从控制台运行它时,它已经完成了对该原型的修改,而在您的测试中,您正在添加到原型,然后第一次构建按钮(这再次更改了原型),然后尝试给你的旧电话打电话,但它已经不存在了。

© www.soinside.com 2019 - 2024. All rights reserved.