在aem 6.2中使用ExtJs编写自定义xtype脚本来开发多字段



嗨,我是ExtJs脚本的新手,我试图开发自定义多字段,我能够理解节点创建部分,但在脚本部分,我无法捕获一些东西,如在侦听器中添加范围:this, fn:this。我试着用谷歌搜索答案,但我没有得到任何令人满意的答案。所以谁能给我解释一下范围:这个部分以及为什么我们在initcomponent中调用超类构造函数,任何相关的资源也欢迎使用

提前感谢爱写代码

Ejst.CustomWidget = CQ.Ext.extend(CQ.form.CompositeField, {
    /**
     * @private
     * @type CQ.Ext.form.TextField
     */
    hiddenField: null,
    /**
     * @private
     * @type CQ.Ext.form.ComboBox
     */
    allowField: null,
    /**
     * @private
     * @type CQ.Ext.form.TextField
     */
    otherField: null,
    constructor: function(config) {
        config = config || { };
        var defaults = {
            "border": false,
            "layout": "table",
            "columns":2
        };
        config = CQ.Util.applyDefaults(config, defaults);
        Ejst.CustomWidget.superclass.constructor.call(this, config);
    },
    // overriding CQ.Ext.Component#initComponent
    initComponent: function() {
        Ejst.CustomWidget.superclass.initComponent.call(this);
        this.hiddenField = new CQ.Ext.form.Hidden({
            name: this.name
        });
        this.add(this.hiddenField);
        this.allowField = new CQ.form.Selection({
            type:"select",
            cls:"ejst-customwidget-1",
            listeners: {
                selectionchanged: {
                    scope:this,
                    fn: this.updateHidden
                }
            },
            optionsProvider: this.optionsProvider
        });
        this.add(this.allowField);
        this.otherField = new CQ.Ext.form.TextField({
            cls:"ejst-customwidget-2",
            listeners: {
                change: {
                    **scope:this,
                    fn:this.updateHidden**
                }
            }
        });
        this.add(this.otherField);
    },
    // overriding CQ.form.CompositeField#processPath
    processPath: function(path) {
        console.log("CustomWidget#processPath", path);
        this.allowField.processPath(path);
    },
    // overriding CQ.form.CompositeField#processRecord
    processRecord: function(record, path) {
        console.log("CustomWidget#processRecord", path, record);
        this.allowField.processRecord(record, path);
    },
    // overriding CQ.form.CompositeField#setValue
    setValue: function(value) {
        var parts = value.split("/");
        this.allowField.setValue(parts[0]);
        this.otherField.setValue(parts[1]);
        this.hiddenField.setValue(value);
    },
    // overriding CQ.form.CompositeField#getValue
    getValue: function() {
        return this.getRawValue();
    },
    // overriding CQ.form.CompositeField#getRawValue
    getRawValue: function() {
        if (!this.allowField) {
            return null;
        }
        return this.allowField.getValue() + "/" +
               this.otherField.getValue();
    },
    // private
    updateHidden: function() {
        this.hiddenField.setValue(this.getValue());
    }
});
// register xtype
CQ.Ext.reg('ejstcustom', Ejst.CustomWidget);

类层次结构,超类构造函数:

你正在调用超类initComponent函数,因为你想让派生类的层次结构的功能可用。

例如,如果你想构造一个大象:

    首先,你设置一些属性,如"大"one_answers"灰色"one_answers"女性"。
  • 然后你构建一个哺乳动物与这些属性。
  • 哺乳动物类的构造函数会自己设置一些属性,比如"has a head",然后调用动物的构造函数,所以如果你不从elephant调用哺乳动物的构造函数,你根本就没有得到一个动物!
  • 动物构造器将检查属性并创建一个动物。
  • 然后,哺乳动物类将添加动物类没有涵盖的细节,例如乳房。
  • 哺乳动物构造函数完成后,大象构造函数添加哺乳动物类没有涉及的细节,例如躯干。

如果你要使用标准的ExtJS语法(不确定CQ是否有自己的"标准语法"),大象的定义看起来像这样:

Ext.define('Elephant',{
    extend:'Mammal',
    initComponent:function() {
        var me = this;
        // set config properties. Two possible calls:
        // "Ext.apply" overwrites config properties already defined by the subclass before constructor has been called
        // "Ext.applyIf" only sets config properties that have NOT been set by the subclass!
        // Since a MiniElephant subclass may want to set size:"small", we use applyIf here.
        Ext.applyIf(me,{ 
            size:'big',
            color:'gray'
        });
        me.callParent(arguments); // <- call constructor of superclass
        me.addTrunk(); // <- postprocessing
    },
    addTrunk:function() {
        var trunk = Ext.create('Trunk',{
            ...
        });
        me.getHead().add(trunk);
        // since addTrunk is called after the mammal constructor has been executed, 
        // the head is already initialized and the getHead function available!
    }
});
Ext.define('Mammal',{
    extend:'Animal',
    initComponent:function() {
        var me = this;
        // Every mammal has a head, so we force the property into here using "apply"!
        Ext.apply({
            hasHead:true,
            ...
        });
        me.callParent(arguments); // <- construct animal
        me.addBreast(); // <- add breast
    },
    getHead:function() {
        return this.headerEl;
    },
    ...
});
<标题>侦听器范围:

监听器是一个函数。每个函数都有一个所谓的scope,它是当你从函数内部访问this时得到的对象。只要你在函数中不使用this, scope对你来说是无关紧要的。

默认情况下,在JavaScript中,函数的作用域是该函数所附加的对象,所以如果你有一个对象

var listener = {更新:函数(){console.log(这个);}

};

如果你像这样调用函数:

listeners.update()

它将把监听对象记录到控制台;但是如果你这样做:

var fn = listeners.update;
fn();

它不会!可以通过调用以下函数来设置函数的作用域:

listeners.update.call(myScope, firstParameter, secondParameter, ...)

或者

listeners.update.apply(myScope, parameterArray)

(好记住:页的 rray !)

因为,在ExtJS中,监听器的配置是由一个Observable mixin处理的,它把函数放入了特别制作的子对象中,默认的作用域对ExtJS程序员来说根本没有意义,所以他们改变了它。为了方便,ExtJS添加了一个config属性,程序员可以使用它来定义他想要的函数的scope

所以如果你定义一个面板并在里面添加一个字段:

Ext.apply(me, {
    items:[{
        xtype:'textfield',
        listeners:{
            update:function() {
                console.log(this); // <- returns the panel, because...
            },
            scope:me // <- we are scoping to the panel!
        }
    }
});

最新更新