Javascript 无法重写setter函数,如setWidth

Javascript 无法重写setter函数,如setWidth,javascript,qooxdoo,Javascript,Qooxdoo,我有以下代码 qx.Class.define("myproject.EditorArea", { extend : qx.ui.container.Composite, events : { }, statics : { }, members : { __htmlArea : null, __txtArea : null, setWidth : function( value ) { this.__html

我有以下代码

qx.Class.define("myproject.EditorArea",
{
  extend : qx.ui.container.Composite,

  events : {
  },

   statics :
   {
   },

  members :
  {
    __htmlArea : null,
    __txtArea : null,

    setWidth : function( value )
    {
      this.__htmlArea.setWidth( value );
      this.__txtArea.setWidth( value );
      return( value );
    },
    setHeight : function( value )
    {
      this.__htmlArea.setHeight( value -19 );
      this.__txtArea.setHeight( value -19 );
      return( value );
    }

},

   /**
    * Constructor
   * @param sHtml {String} the initial html value for this widget.
    */
   construct : function( sHtml )
  {
   this.base(arguments);

    this.setLayout( new qx.ui.layout.VBox(1));

    var container = new qx.ui.container.Composite(new qx.ui.layout.HBox( 1, "right" )).set( {height:18} );
    this.__htmlArea = new qx.ui.embed.Html( sHtml );
    this.add(this.__htmlArea);
    this.__txtArea = new qx.ui.form.TextArea("");
  }
});
当从类EditorArea调用setWidth()时,框架总是调用超级函数

换句话说

var editor = new myproject.EditorArea( somehtml );
editor.setWidth( 460 );
调用qx.ui.container.Composite.setWidth()而不是 myproject.EditorArea.setWidth()


永远不会到达重写的函数。如何重写这些setter函数?

getter和setter函数是在qx.Class.define()期间通过编程生成的。通常情况下,你不想和他们捣乱。如果您想要自己的,最好创建setMyWidth()和setMyHeight()函数,即一些非自动生成名称的函数

如果您确实希望函数名为setWidth/setHeight,您可以尝试在类定义的defer部分创建这些函数。传递给qx.Class.define的映射的defer元素与construct、events、statics、members(参见文档)处于同一级别,其函数中的代码在类完全定义后运行。通过在其中添加自定义函数,您可以覆盖/完全覆盖自动生成的getter和setter。不过,你现在处在一个未知的领域,我不建议这样做


Derrell

正如Derrell已经说过的,通过技巧可以覆盖qooxdoo属性的自动生成setter和getter,但不推荐这样做

但是可能有一个解决方案,可以通过覆盖属性applyer
\u applyDimension
来定义宽度和高度,该属性在
qx.ui.core.LayoutItem
中定义

每次属性更改时都会调用applyer。请阅读相应的文档,网址为

您的覆盖将如下所示:

\u applyDimension:function(newValue、oldValue、propertyName){
如果(propertyName==“宽度”){
此.uuu htmlArea.setWidth(newValue);
此.u xtarea.setWidth(newValue);
}
如果(propertyName==“高度”){
此.htmlArea.setWidth(newValue-19);
此._utxtarea.setWidth(newValue-19);
}
this.base(参数、newValue、oldValue、propertyName);
}
通过在此处调用
this.base(arguments,…)
来调用超类方法非常重要,这样就不会中断继承路径上的上游功能,当然,您也可以显式地这样做


这种方法是安全的,并且有文档记录。

另外,为了补充讨论,当我们设置属性时,有时我们不想同时做其他事情,就像这个问题一样。我们可能还希望在设置值、验证值或只是检查其格式是否正确之前对其进行转换。除此之外,apply qooxdo还提供了属性定义中的其他键。比如说

properties : {
  myProp : {
        apply : "_applyMyProp",
        transform: "_transformMyProp",
        check: "_checkMyProp",  
        validate: "_validateMyProp"}
},

members :
{
  _applyMyProp : function(value, old, name) {
    // do something with the value 
  },

  _transformMyProp: function(value){
    // transform the value before being checked and validated and set
  },

  _checkMyProp: function(value){
    // check the value when on debug mode
  },

  _validateMyProp: function(value){
   // validate the value before set even when not in debug mode
  },
}

以下是更多细节

这不是qooxdoo方式,因为:

  • 要解决此任务,您通常使用绑定+侦听器+布局管理器
  • 在这种情况下,属性设置器工作得很快,因为布局管理器在其队列中安排更新,但如果它运行缓慢呢?该属性的设计是为了快速,让开发人员易于阅读。Setter/getter调用不能花费太多时间

  • 未调用setHeight和setWidth的原因是因为在示例中从未调用它们;请看一下您的示例的这个版本,您可以看到,如果调用派生类,则会调用它们中的setWidth/setHeight(您需要单击“Log”按钮来查看证明这一点的调试输出)

    (但是,请注意,虽然这在操场上起作用,但调试编译器将阻止您重写属性访问器-我在这里讨论了一个问题)

    您试图实现的更大的目标是在另一个小部件中嵌入小部件并控制布局-但是您所采取的方法将不起作用,因为您没有调用超级类setWidth和setHeight,这意味着您将阻止小部件具有零宽度和高度以外的任何内容。无论你的htmlarea和文本区域有多大,它们都不会被看到,因为它们的容器是零宽度/高度

    改变布局工作方式的正确方法是选择不同的布局(即qx.ui.layout.*类)或可能编写自己的布局,尽管鉴于现有布局类的灵活性,很少需要这样做


    ::编辑::尽管我在上面提到调试编译器不允许重写属性访问器,但这一点在2016年6月22日已发生更改。Qooxdoo已经升级,支持覆盖超类中定义的属性访问器方法;这是主分支,将是Qooxdoo 6.0稳定版的一部分

    让我像Clippy一样突然说:看起来你正在尝试制作自己的小部件。qooxdoo有一个推荐的并且有很好文档记录的方法来做这件事,我认为如果你遵循这个方法,你会过得更好。既然这不是你的问题,我就不想再多说了。这里有一些链接。如果你需要帮助,请在这里询问。此外,我认为数据绑定更适合您的情况。同样,因为问题不是关于数据绑定的,所以我不打算详细介绍,但这里有一个链接可以帮助您开始。如果需要帮助,请再次询问
    qx.Class.define("myproject.EditorArea", {
      extend: qx.ui.container.Composite,
    
      members: {
        __htmlArea: null,
        __txtArea: null,
    
        setWidth: function(value) {
          this.debug("in setWidth");
          this.__htmlArea.setWidth(value);
          this.__txtArea.setWidth(value);
          return (value);
        },
        setHeight: function(value) {
          this.debug("in setHeight");
          this.__htmlArea.setHeight(value - 19);
          this.__txtArea.setHeight(value - 19);
          return (value);
        }
    
      },
    
      construct: function(sHtml) {
        this.base(arguments);
    
        this.setLayout(new qx.ui.layout.VBox(1));
        this.__htmlArea = new qx.ui.embed.Html(sHtml);
        this.add(this.__htmlArea);
        this.__txtArea = new qx.ui.form.TextArea("");
      }
    });
    
    var test = new myproject.EditorArea();
    test.set({ width: 200, height: 300 }); // outputs "in setWidth" and "in setHeight" 
    test.set({ width: 250, height: 350 }); // outputs "in setWidth" and "in setHeight"