Javascript/ExtJS:“一个;条件继承;?

Javascript/ExtJS:“一个;条件继承;?,javascript,inheritance,extjs,Javascript,Inheritance,Extjs,我们将ExtJS用于Web应用程序。在该应用程序中,当需要一个简单的下拉列表时,我们使用标准的Ext.form.ComboBox控件;当需要一个下拉列表时,我们使用Ext.us.Andrie.Select控件,您可以选择多个值和/或清除值。创建这两个选项中的任何一个总是需要一堆用于配置选项的样板代码,因此我想要一个能够减少样板代码的类,并且当我使用它时,我希望这个类能够生成简单的下拉列表,或者更高级的下拉列表,具体取决于配置选项(multi:true或clearable:true),但事实证明,

我们将ExtJS用于Web应用程序。在该应用程序中,当需要一个简单的下拉列表时,我们使用标准的
Ext.form.ComboBox
控件;当需要一个下拉列表时,我们使用
Ext.us.Andrie.Select
控件,您可以选择多个值和/或清除值。创建这两个选项中的任何一个总是需要一堆用于配置选项的样板代码,因此我想要一个能够减少样板代码的类,并且当我使用它时,我希望这个类能够生成简单的下拉列表,或者更高级的下拉列表,具体取决于配置选项(
multi:true
clearable:true
),但事实证明,这比预期的困难得多

这是我最接近工作结果的一次:

MyComboBox = (function() {

    var singleDefaults = {
        typeAhead: false,
        triggerAction: 'all',
        selectOnFocus: false,
        allowBlank: true,
        editable: false,
        delay: 700
    };

    var multiDefaults = {
        typeAhead: false,
        triggerAction: 'all',
        selectOnFocus: false,
        allowBlank: true,
        editable: false,
        delay: 700
    };

    var constructor = function(config) {

            if (config.multi || config.clearable) {
                config = Ext.apply(this, config, multiDefaults);
                Ext.apply(this, Ext.ux.Andrie.Select.prototype);
                Ext.apply(this, Ext.ux.Andrie.Select(config));
                Ext.ux.Andrie.Select.prototype.constructor.call(this, config);
            } else {
                config = Ext.apply(this, config, singleDefaults);
                Ext.apply(this, Ext.form.ComboBox.prototype);
                Ext.apply(this, Ext.form.ComboBox(config));
                Ext.form.ComboBox.prototype.constructor.call(this, config);
            }
    };

    return function(config) {
        this.constructor = constructor;
        this.constructor(config);
    };

})();
嗯,它不会崩溃,但也不会真正起作用。如果设置为类似于
Ext.ux.Andrie.Select
,则即使在加载存储时,它也希望加载存储,除非您开始在字段中键入,否则不会展开下拉列表

另一种尝试的方法是:

MyComboBox = Ext.extend(Ext.form.ComboBox, {
 constructor: function(config){
   if (config.multi || config.clearable) {
     Ext.form.ComboBox.prototype.constructor.call(this, config);
   } else {
     Ext.ux.Andrie.Select.prototype.constructor.call(this, config);
   }
 }
});
这不起作用,因为Andrie下拉列表没有定义自己的
构造函数
函数,所以它最终调用了它继承的
Ext.form.ComboBox
的构造函数,这会导致正常的下拉列表,而不是multiselect下拉列表


我认为这是特定于ExtJS的,但如果您有一种不依赖框架的方法来实现这一点,我可能会将其转换为ExtJS

在构建中大规模JavaScript应用程序时,我发现将所有控件创建/实例化移动到一个类中非常方便,因为每个方法都是该控件的工厂(即:组合框、文本区域、按钮、工具提示、复选框等)。由于只有您的工厂类知道如何创建控件,因此这还具有将视图逻辑与控件实例化本身分离的额外好处(当然,只要控件构造函数和接口保持不变)

从视图中解耦控件创建允许您快速轻松地将一个控件的实现切换到另一个控件,而无需搜索整个应用程序来查找/替换该控件创建样板的所有实例


编辑:
我的意思并不是说这将取代使用对象来创建/实例化控件,而是说,除此之外还要使用对象。使用
WidgetFactory
作为所有控件的单一网关比仅更改超类更具灵活性。您可以在不改变原始类的情况下交换整个类,从而在必要时允许有多个不同的实现

例如,如果您的单个组合框是由某个类定义的,
namespace.ui.combobox.single
,则可以执行以下操作:

comboBoxSingle: function(config) {
    return new namespace.ui.combobox.single(config);
},
但是,如果您突然需要使用不同的类进行测试,您可以在工厂中更改它一次

comboBoxSingle: function(config) {
    return new namespace.ui.combobox.single2(config);
},

无需更改实际的小部件类即可轻松地来回切换。

在构建中大规模JavaScript应用程序时,我发现将所有控件创建/实例化移动到单个类中非常方便,因为每个方法都是该控件的工厂(例如:组合框、文本区域、按钮、工具提示、复选框等)。由于只有您的factory类知道如何创建控件,因此这还有一个额外的好处:将视图逻辑与控件实例化本身分离(当然,只要控件构造函数和接口保持不变)

从视图中解耦控件创建允许您快速轻松地将一个控件的实现切换到另一个控件,而无需搜索整个应用程序来查找/替换该控件创建样板的所有实例


编辑:
我的意思并不是说这将取代使用对象来创建/实例化控件,而是说,除了使用对象之外,还可以使用对象。使用
WidgetFactory
作为所有控件的单一网关,不仅可以更改超类,还允许更大的灵活性。您可以在不更改原始类的情况下交换整个类l类,允许您在必要时有多个不同的实现

例如,如果您的单个组合框是由某个类定义的,
namespace.ui.combobox.single
,则可以执行以下操作:

comboBoxSingle: function(config) {
    return new namespace.ui.combobox.single(config);
},
但是,如果您突然需要使用不同的类进行测试,您可以在工厂中更改它一次

comboBoxSingle: function(config) {
    return new namespace.ui.combobox.single2(config);
},

无需更改实际的小部件类即可轻松地来回切换。

几乎忘记了这个问题。我解决了这个问题,如果有人想知道,下面是如何做到的:

var constructor = function(config) {
    if (config && (config.multi || config.clearable)) {
        config = Ext.apply(this, config, multiDefaults);
        Ext.applyIf(this, Ext.ux.Andrie.Select.prototype);
        Ext.ux.Andrie.Select.createDelegate(this)(config);
    } else {
        config = Ext.apply(this, config, singleDefaults);
        Ext.applyIf(this, Ext.form.ComboBox.prototype);
        Ext.form.ComboBox.createDelegate(this)(config);
    }
};

差点忘了这个问题。我解决了这个问题,如果有人想知道,下面是怎么做的:

var constructor = function(config) {
    if (config && (config.multi || config.clearable)) {
        config = Ext.apply(this, config, multiDefaults);
        Ext.applyIf(this, Ext.ux.Andrie.Select.prototype);
        Ext.ux.Andrie.Select.createDelegate(this)(config);
    } else {
        config = Ext.apply(this, config, singleDefaults);
        Ext.applyIf(this, Ext.form.ComboBox.prototype);
        Ext.form.ComboBox.createDelegate(this)(config);
    }
};

创建类当然是一个有效且好的建议,但也可以减少耦合。我可以随时更改MyComboBox的实现,例如从
Ext.form.TextField
继承(错误,但完全可能)。唯一真正的区别是语义,我使用
new
,而您使用工厂方法。创建类当然是一个有效且好的建议,但也可以减少耦合。我可以随时更改MyComboBox的实现,例如从
Ext.form.TextField
继承(错误,但完全可能)唯一真正的区别是语义,我使用
new
,而你使用的是工厂方法。