extjs - initComponent()या initComponent()करने के लिए




extjs4 extjs4.1 (5)

सबसे पहले मैं अपनी टिप्पणियों पर खड़ा रहूंगा:

@AlexanderTokarev मुझे गलत मत समझो। मैं घटकों की कॉन्फ़िगरेशन के बारे में बात नहीं करता, या उदाहरणों के बहुत खराब और उन्हें initComponent() ले जा रहा हूं, यह मेरा मुद्दा नहीं है।

अब मैं इसके बारे में क्या सोचता हूं।

initComponent () इस वर्ग के एक उदाहरण के समय आवश्यक कुछ भी हल करना चाहिए। न आधिक न कम।

कक्षाओं को परिभाषित करते समय आप लोड को गड़बड़ कर सकते हैं और इसमें से अधिकांश ऐसा इसलिए होता है क्योंकि लोग समझ नहीं पाते कि एक्स्टजेस क्लास-सिस्टम कैसे काम करता है। चूंकि यह घटकों के बारे में है, तो निम्नलिखित उन पर ध्यान केंद्रित करेंगे। यह एक सरलीकृत उदाहरण भी होगा जो केवल एक प्रकार की त्रुटि दिखाएगा जिसे मैंने कई बार देखा है।

आइए शुरू करें: हमारे पास एक कस्टम पैनल है जो बहुत सी निफ्टी चीजें करता है। इससे कस्टम कॉन्फ़िगरेशन की आवश्यकता आती है, हम इसे foo कहते हैं। हम इसे क्लास परिभाषा के लिए हमारे डिफ़ॉल्ट कॉन्फ़िगरेशन विकल्प के साथ जोड़ते हैं ताकि हम इसे एक्सेस कर सकें:

Ext.define('Custom', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.custpanel',

    foo: {
        bar: null  
    },

    initComponent: function() {
        this.callParent(arguments);
    }
});

लेकिन परीक्षण के बाद चीजें अजीब हो जाती हैं। हमारे विन्यास के मूल्य जादुई रूप से बदलते प्रतीत होता है। यहां एक JSFiddle क्या हुआ है कि सभी बनाए गए उदाहरण एक ही foo उदाहरण का जिक्र कर रहे हैं। लेकिन हाल ही में मैंने ऐसा किया है

store: {
    fields: [ ... ],
    proxy: {
        type: 'direct',
        directFn: 'Direct.Store.getData'
    }
}

एक दुकान के साथ और वह काम किया। तो क्यों काम नहीं करता है?

अधिकांश लोगों को इस छोटी foo ऑब्जेक्ट और एक (ExtJS) कॉन्फ़िगरेशन के बीच कोई अंतर नहीं दिखता है जो मूल रूप से सही है क्योंकि दोनों वस्तुएं (उदाहरण) हैं। लेकिन अंतर यह है कि सेन्चा द्वारा भेजे गए सभी वर्गों को पूरी तरह से पता है कि वे किस कॉन्फ़िगरेशन गुणों की अपेक्षा करते हैं और उनका ख्याल रखते हैं।

उदाहरण के लिए StoreManager द्वारा ग्रिड की स्टोर प्रॉपर्टी का समाधान किया जाता है और इसलिए यह हो सकता है:

  • storeId स्ट्रिंग, या
  • स्टोर उदाहरण या
  • स्टोर कॉन्फ़िगरेशन ऑब्जेक्ट।

ग्रिड के प्रारंभ के दौरान इनमें से कोई भी वास्तविक स्टोर इंस्टेंस द्वारा हल और अधिलेखित हो जाता है। एक दुकान सिर्फ एक उदाहरण है। मुझे लगता है कि अधिक ज्ञात एक आइटम सरणी है। यह परिभाषा समय पर एक सरणी है और यह मिश्रित कोलेक्शन (यदि मुझे गलत नहीं है) के साथ प्रत्येक उदाहरण के लिए ओवरराइड हो जाता है।

हां कक्षा परिभाषा और इसके द्वारा बनाए गए उदाहरण के बीच एक अंतर है। लेकिन हमें किसी भी नई संपत्ति का ख्याल रखने की आवश्यकता है जिसमें ऊपर से foo जैसे संदर्भ शामिल हैं और यह जटिल नहीं है। यहां foo उदाहरण के लिए इसे ठीक करने के लिए हमें क्या करना है

Ext.define('Custom', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.custpanel',

    foo: {
        bar: null  
    },

    initComponent: function() {
        this.foo = Ext.apply({}, this.foo);
        this.callParent(arguments);
    }
});

JSFiddle यहाँ है

जब हम एक उदाहरण बनते हैं तो हम foo कॉन्फ़िगरेशन का ख्याल रखते हैं। अब यह foo उदाहरण सरलीकृत है और कॉन्फ़िगरेशन को हल करना हमेशा आसान नहीं होगा।

निष्कर्ष

कॉन्फ़िगरेशन के रूप में हमेशा अपनी कक्षा परिभाषा लिखें! उनमें सादे कॉन्फ़िगरेशन को छोड़कर किसी भी संदर्भित उदाहरण नहीं होना चाहिए और उदाहरण के दौरान उन्हें हल करने के लिए इनका ध्यान रखना चाहिए।

अस्वीकरण

मैं इस वास्तव में छोटे लेखन के साथ सभी को कवर करने का दावा नहीं करता!

मैं एक्स्टजेस 4 में ऐप बनाने के दौरान संघर्ष करता हूं, और उसमें से कुछ हिस्सा initComponent () में कब कॉन्फ़िगर करना है और जब नहीं ...

उदाहरण के लिए, सेन्चा के स्वयं के एमवीसी अनुप्रयोग आर्किटेक्चर दस्तावेज़ में, जब पहली बार ग्रिड व्यू बनाते हैं, तो उन्होंने initComponent () विधि में इनलाइन स्टोर को परिभाषित किया। (देखें "एक दृश्य परिभाषित करें" खंड)

आगे नीचे, जब उन्होंने स्टोर को एक अलग वर्ग में फैक्टर किया, तो उन्होंने परिभाषा को initComponent () के बाहर ले जाया। एक उपयोगी टिप्पणी है जो इस तथ्य पर ध्यान खींचती है, लेकिन कोई स्पष्टीकरण नहीं है। (एक मॉडल और स्टोर अनुभाग बनाना देखें)

मुझे लगता है कि कारण स्पष्ट होना चाहिए, लेकिन मुझे यह याद आ रही है। कोई संकेतक?


मैं आमतौर पर क्लास कॉन्फ़िगरेशन विकल्पों में जितना संभव हो उतना कॉन्फ़िगरेशन करने का समर्थन करता हूं, क्योंकि यह बेहतर पढ़ता है और सबक्लास में ओवरराइड करना आसान होता है। इसके अलावा, एक मजबूत संभावना है कि भविष्य में सेन्चा सीएमडी को संकलक अनुकूलित करना होगा ताकि यदि आप अपना कोड घोषणात्मक रखते हैं, तो यह अनुकूलन से लाभान्वित हो सकता है।

की तुलना करें:

Ext.define('MyPanel', {
    extend: 'Ext.grid.Panel',

    initComponent: function() {
        this.callParent();
        this.store = new Ext.data.Store({
            fields: [ ... ],
            proxy: {
                type: 'direct',
                directFn: Direct.Store.getData
            }
        });
        this.foo = 'bar';
    }
});

...

var panel = new MyPanel();

तथा:

Ext.define('MyPanel', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.mypanel',

    foo: 'bar',

    store: {
        fields: [ ... ],
        proxy: {
            type: 'direct',
            directFn: 'Direct.Store.getData'
        }
    }
});

...

var panel = Ext.widget({
    xtype: 'mypanel',
    foo: 'baz'
});

ध्यान दें कि ये दृष्टिकोण कितने अलग हैं। पहले उदाहरण में, हम बहुत कड़ी मेहनत कर रहे हैं: ऑब्जेक्ट प्रॉपर्टी वैल्यू, स्टोर कॉन्फ़िगरेशन, माइपेनल क्लास का नाम जब इसका उपयोग किया जाता है; हम व्यावहारिक रूप से कक्षा के विचार को मार रहे हैं क्योंकि यह अतुलनीय हो जाता है। दूसरे उदाहरण में, हम एक टेम्पलेट बना रहे हैं जिसे संभावित रूप से अलग-अलग कॉन्फ़िगरेशन के साथ कई बार पुन: उपयोग किया जा सकता है - मूल रूप से, यह पूरी कक्षा प्रणाली के बारे में है।

हालांकि, वास्तविक अंतर गहरा है। पहले मामले में, हम प्रभावी ढंग से रनटाइम तक क्लास कॉन्फ़िगरेशन का निर्धारण कर रहे हैं, जबकि दूसरे मामले में हम कक्षा कॉन्फ़िगरेशन को परिभाषित कर रहे हैं और इसे बहुत अलग चरणों पर लागू कर रहे हैं। असल में, हम आसानी से कह सकते हैं कि दूसरा दृष्टिकोण कुछ जावास्क्रिप्ट को मूल रूप से कम करता है: समय चरण संकलित करें। और यह हमें ढांचे की एक बड़ी संभावना देता है जिसका उपयोग फ्रेमवर्क कोड में ही किया जाता है; अगर आप कुछ उदाहरण चाहते हैं, तो नवीनतम 4.2 बीटा में Ext.app.Controller और Ext.app.Application पर एक नज़र डालें।

अधिक व्यावहारिक परिप्रेक्ष्य से, दूसरा दृष्टिकोण बेहतर है क्योंकि इसे पढ़ने और निपटना आसान है। एक बार जब आप इस विचार को समझ लेंगे, तो आप खुद को अपना पूरा कोड लिखेंगे, क्योंकि यह इस तरह से आसान है।

इसे इस तरह देखो: यदि आप पुराने शैली के वेब एप्लिकेशन को लिखते हैं, तो सर्वर और एचटीएमएल की तरफ से सर्वर तैयार करते हैं, तो आप कोड के साथ मिश्रित एचटीएमएल नहीं रखने का प्रयास करेंगे, है ना? बाईं ओर टेम्पलेट, दाईं ओर कोड। यह व्यावहारिक रूप से initComponent में हार्डकोडिंग डेटा जैसा ही है: सुनिश्चित करें कि यह एक बिंदु तक काम करता है। फिर यह स्पेगेटी का एक कटोरा बन जाता है, जो बनाए रखने और विस्तार करने के लिए कठिन होता है। ओह, और यह सब परीक्षण! छी।

अब, ऐसे समय होते हैं जब आपको रनटाइम पर किसी उदाहरण के साथ कुछ करने की आवश्यकता होती है, क्लास परिभाषा समय के विपरीत - शास्त्रीय उदाहरण ईवेंट श्रोताओं को लागू कर रहा है, या नियंत्रकों में control कॉल कर रहा है। आपको ऑब्जेक्ट इंस्टेंस से वास्तविक फ़ंक्शन संदर्भ लेना होगा, और आपको इसे initComponent या init । हालांकि, हम इस समस्या को आसान बनाने पर काम कर रहे हैं - इस सबको हार्डकोड करने के लिए कोई कठोर आवश्यकता नहीं होनी चाहिए; Observable.on() पहले ही स्ट्रिंग श्रोता नामों और एमवीसी सामान का समर्थन करता है, जल्द ही।

जैसा कि मैंने उपर्युक्त टिप्पणियों में कहा था, मुझे दस्तावेज़ों के बारे में एक लेख लिखना होगा या चीजों को समझाएं। इसे शायद 4.2 तक जारी होने तक इंतजार करना पड़ेगा; इस बीच, इस जवाब को इस मामले पर कुछ प्रकाश डालना चाहिए, उम्मीद है कि।


जब मैं यहां समाप्त हुआ और इन उत्तरों को देखकर मुझे निराश कर दिया, तो मैं उसी प्रश्न का उत्तर खोज रहा हूं। इनमें से कोई भी सवाल का जवाब नहीं देता है: initComponent () या कन्स्ट्रक्टर?

यह जानना अच्छा है कि क्लास कॉन्फ़िगरेशन ऑब्जेक्ट ऑब्जेक्ट्स साझा किए जाते हैं और आपको प्रति उदाहरण उन्हें प्रारंभ / संसाधित करने की आवश्यकता होती है, लेकिन कोड कन्स्ट्रक्टर के साथ-साथ initComponent () फ़ंक्शन में भी जा सकता है।

मेरा अनुमान था कि घटक वर्ग का निर्माता मध्य में कहीं भी initComponent () को कॉल करता है और मैं बहुत गलत नहीं था: बस स्रोत कोड को देखना था, यह वास्तव में सारकंपोनेंट का निर्माता है

तो ऐसा लगता है:

AbstractComponent/ctor:
- stuffBeforeIC()
- initComponent()
- stuffAfterIC()

अब यदि आप एक घटक का विस्तार करते हैं, तो आपको ऐसा कुछ मिल जाएगा:

constructor: function () {
  yourStuffBefore();
  this.callParent(arguments);
  yourStuffAfter();
},
initComponent: function () {
  this.callParent();
  yourInitComp()
}

अंतिम आदेश इन्हें बुलाया जाता है:

- yourStuffBefore()
- base's ctor by callParent:
  - stuffBeforeIC()
  - initComponent:
    - base's initComponent by callParent
    - yourInitComp()
  - stuffAfterIC()
- yourStuffAfter()

तो अंत में यह सब इस बात पर निर्भर करता है कि क्या आप सामान के बीच अपना कोड इंजेक्ट करना चाहते हैं / सामान और सामान के बाद, जिसे आप कक्षा के निर्माता में देख सकते हैं जिसे आप विस्तारित करने जा रहे हैं।


यदि आपको एक्स्टजेस क्लास सिस्टम कैसे काम करता है, इसकी गहरी समझ नहीं है, तो आप इसका पालन करना चाहेंगे:

initComponent() में सभी गैर-आदिम प्रकारों को initComponent()

शब्दावली

  • आदिम प्रकार - तार, बूलियन, पूर्णांक, आदि
  • गैर-Primitives - सरणी और वस्तुओं।

व्याख्या

यदि आपके द्वारा विस्तारित घटक को एक से अधिक बार बनाया जाना है, तो कॉन्फ़िगरेशन विकल्प ( initComponent बाहर) के रूप में घोषित किसी भी गैर-आदिम कॉन्फ़िगरेशन को सभी उदाहरणों के बीच साझा किया जाएगा।

इस वजह से, कई लोगों ने मुद्दों का अनुभव किया जब एक विस्तारित घटक (आमतौर पर एक विस्तारित ग्रिड) एक से अधिक टैब पर बनाया जाता है।

इस व्यवहार को नीचे के जवाब में और इस स्कर्टल के डेन आलेख में समझाया गया है। आप यह SO प्रश्न भी पढ़ना चाहेंगे।


@RobAgar के उत्तर को विस्तारित करने के लिए, एक बहुत ही सरल दिनांक समय फ़ील्ड के बाद मैंने एक्स्टजेएस 3 के लिए लिखा था और यह एक्स्टजेस 4 के लिए बनाया गया क्विकपोर्ट है। महत्वपूर्ण बात Ext.form.field.Field mixin का उपयोग है। यह मिश्रण तार्किक व्यवहार और फॉर्म फ़ील्ड की स्थिति के लिए एक सामान्य इंटरफ़ेस प्रदान करता है, जिसमें निम्न शामिल हैं:

क्षेत्र मूल्यों के लिए गेटटर और सेटर विधियां मूल्य और वैधता परिवर्तनों को ट्रैक करने के लिए ईवेंट और विधियां सत्यापन को ट्रिगर करने के तरीके

इसका उपयोग कई क्षेत्रों के संयोजन के लिए किया जा सकता है और उन्हें एक के रूप में कार्य करने दें। कुल कस्टम Ext.form.field.Base लिए मैं Ext.form.field.Base का विस्तार करने की अनुशंसा करता हूं

यहां उदाहरण दिया गया है कि मैंने उपर्युक्त उल्लेख किया है। यह जूता होना चाहिए कि डेट ऑब्जेक्ट की तरह कुछ भी करने के लिए यह कितना आसान हो सकता है जहां हमें गेटर और सेटर के भीतर डेटा को प्रारूपित करने की आवश्यकता होती है।

Ext.define('QWA.form.field.DateTime', {
    extend: 'Ext.form.FieldContainer',
    mixins: {
        field: 'Ext.form.field.Field'
    },
    alias: 'widget.datetimefield',
    layout: 'hbox',
    width: 200,
    height: 22,
    combineErrors: true,
    msgTarget: 'side',
    submitFormat: 'c',

    dateCfg: null,
    timeCfg: null,

    initComponent: function () {
        var me = this;
        if (!me.dateCfg) me.dateCfg = {};
        if (!me.timeCfg) me.timeCfg = {};
        me.buildField();
        me.callParent();
        me.dateField = me.down('datefield')
        me.timeField = me.down('timefield')

        me.initField();
    },

    //@private
    buildField: function () {
        var me = this;
        me.items = [
        Ext.apply({
            xtype: 'datefield',
            submitValue: false,
            format: 'd.m.Y',
            width: 100,
            flex: 2
        }, me.dateCfg),
        Ext.apply({
            xtype: 'timefield',
            submitValue: false,
            format: 'H:i',
            width: 80,
            flex: 1
        }, me.timeCfg)]
    },

    getValue: function () {
        var me = this,
            value,
            date = me.dateField.getSubmitValue(),
            dateFormat = me.dateField.format,
            time = me.timeField.getSubmitValue(),
            timeFormat = me.timeField.format;
        if (date) {
            if (time) {
                value = Ext.Date.parse(date + ' ' + time, me.getFormat());
            } else {
                value = me.dateField.getValue();
            }
        }
        return value;
    },

    setValue: function (value) {
        var me = this;
        me.dateField.setValue(value);
        me.timeField.setValue(value);
    },

    getSubmitData: function () {
        var me = this,
            data = null;
        if (!me.disabled && me.submitValue && !me.isFileUpload()) {
            data = {},
            value = me.getValue(),
            data[me.getName()] = '' + value ? Ext.Date.format(value, me.submitFormat) : null;
        }
        return data;
    },

    getFormat: function () {
        var me = this;
        return (me.dateField.submitFormat || me.dateField.format) + " " + (me.timeField.submitFormat || me.timeField.format)
    }
});