2011-08-06 9 views
21

मेरे पास Backbone.View का एक सामान्य उप-वर्ग है जिसमें close ईवेंट श्रोता है।उप वर्ग एक बैकबोन। उप वर्ग देखें और घटनाओं को बनाए रखें

var GenericView = Backbone.View.extend({ 

    events : { 
     "click .close" : "close" 
    }, 

    close : function() { 
     console.log("closing view"); 
    } 

}); 

मैं इस सामान्य वर्ग को उप-वर्ग बनाना चाहता हूं और कुछ नई घटनाएं जोड़ना चाहता हूं। हालांकि नीचे सुपर क्लास (उपरोक्त) ईवेंट ऑब्जेक्ट को ओवरराइट कर देगा। जैसे

var ImplementedView = new GenericView({ 

    // setting this will stop 'close' in Super Class from triggering 
    events : { 
     "click .submit" : "submit" 
    } 

}); 

मैं एक उप वर्ग कैसे बनाना चाहिए, इस मामले ImplementedView में और घटनाओं को बनाए रखने?

मुझे कक्षा वर्ग के निर्माण के दौरान ईवेंट ऑब्जेक्ट को विस्तारित करके इसे प्राप्त करने का एक तरीका मिला है। हालांकि मुझे this.delegateEvents() को फिर से ट्रिगर करने की आवश्यकता है, जिसे मैं अनुमान लगा रहा हूं वह अच्छा नहीं है। क्या कोई इस पर टिप्पणी कर सकता है?

var ImplementedView = new GenericView({ 

    initialize : function (options) { 

     _.extend(this.events, { 
      "click .submit" : "submit" 
     }); 

     // re-attach events 
     this.delegateEvents(); 
    } 

}); 
+0

मैं गलत हो सकता हूं, लेकिन मुझे आपको कहीं भी उपclassing नहीं दिख रहा है ?? कार्यान्वित दृश्य केवल एक चर है जेनेरिक व्यू के उदाहरण का जिक्र है ... – PhD

+0

आपको या तो स्पष्ट रूप से '_.extend (...)' का उपयोग करने की आवश्यकता है या दृश्यों की '.extend' विधि जैसी समान कार्यक्षमता है ... देखो एक सुराग पाने के लिए backbone.js के माध्यम से। लेकिन अगर मैं सही हूं तो यह प्रोटोटाइप श्रृंखला पर स्पष्ट विरासत की कमी के कारण है। 'This.delegateEvents() 'या' Backbone.View.prototype.delegateEvents.call (ईवेंट) को कॉल करना – PhD

+0

पर जाने का तरीका प्रतीत होता है, मैं दस्तावेज़ों को देखूंगा। अपनी पहली टिप्पणी दोबारा: मैं नए ऑपरेटर को नहीं बुला रहा हूं, हालांकि यह बैकबोन को विस्तारित करने के माध्यम से उप-वर्गीकरण कर रहा था। मॉडल? – Ross

उत्तर

28

@Nupul बिल्कुल सही है: यदि आप अपने GenericView उपवर्गीकरण नहीं कर रहे हैं।

असल में, सबक्लासिंग वास्तव में सही शब्द नहीं है, क्योंकि जावास्क्रिप्ट शास्त्रीय विरासत नहीं करता है।

तो चलो पहली कोशिश करते हैं और समझते हैं कि यहाँ क्या हो रहा है:

var GenericView = Backbone.View.extend(propertiesObj, classPropertiesObj) 

Backbone.View एक निर्माता समारोह है, कि जब new कीवर्ड के साथ कहा जाता है, आप के लिए एक नई वस्तु बनाता है।

के बाद से इस जेएस है, सभी कार्य वास्तव में वस्तुओं, ढंग से काम कर रहे हैं ताकि Backbone.View.extend सिर्फ एक Backbone.View है कि कुछ काम करता है पर लटके हुए समारोह है:

  1. यह तो आप गुण एक्सेस कर सकते हैं, प्रोटोटाइप श्रृंखला सेट कॉल 'आधार' में परिभाषित कार्यों वर्ग
  2. यह बनाता है और एक नया निर्माता समारोह आप कॉल कर सकते हैं (जो यहाँ GenericView होगा)
  3. यह प्रतियां अपने आप में एक समारोह पर लटके हुए जा करने के लिए अपने इनहेरीट वर्ग की वस्तुओं का दृष्टांत रिटर्न कन्स्ट्रक्टर फ़ंक्शन यह लौटाता है ताकि आप आगे वारिस कर सकें।

तो protoype श्रृंखला आप चाहते हैं स्थापित करने के लिए सही तरीका है:

var ImplementedView = GenericView.extend({ 
    // implementation goes here 
}); 

और नहीं:

var ImplementedView = new GenericView({//stuff}); 

क्योंकि यह सिर्फ एक GenericView का एक नया उदाहरण बनाता है।

अब, आप अभी भी एक समस्या है, क्योंकि जब आप की तरह कुछ कार्य करें: वहाँ परिणाम आप चाहते हैं पाने के लिए विभिन्न तरीके हैं इस बिंदु पर

var impl_view = new ImplementedView; 

impl_view.events; // This isn't merged with the events you created 
        // for the GenericView 

, यहाँ से एक की तरह है कि आप किस delegateEvents तरह का उपयोग करता है है किया। इसका उपयोग करना, संयोग से बुरा नहीं है।

var GenericView = Backbone.View.extend({ 

    genericEvents: { 'click .close': 'close' }, 

    close: function() { console.log('closing view...'); } 

}); 

var ImplView = GenericView.extend({ 

    events: { 'click .submit': 'submit' }, 

    initialize: function(options) { 
    // done like this so that genericEvents don't overwrite any events 
    // we've defined here (in case they share the same key) 
    this.events = _.extend({}, this.genericEvents, this.events); 
    this.delegateEvents() 
    } 
}); 
+0

धन्यवाद। –

+2

यह एक अच्छा जवाब है। हालांकि नकारात्मक पक्ष को पेस्ट करना पड़ रहा है: 'this.events = _.extend (this.genericEvents, this.events); प्रत्येक सबव्यू के init में। लेकिन मुझे लगता है कि मैं सौदा कर सकता हूं। इच्छा है कि एक और स्वचालित तरीका था हालांकि। –

+0

इस लाइन पर 'param.events = _.extend (this.genericEvents, this.events) पर paramaters का क्रम पीछे है; ' इसे वास्तव में पढ़ना चाहिए -' this.events = _.extend (this.events, this.genericEvents); '। पहला पैरामीटर गंतव्य है, दूसरा स्रोत है। –

1

आप इस उपयोगी लग सकती: मैं http://kalimotxocoding.blogspot.com/2011/03/playing-with-backbonejs-views.html

सेकंड क्या उल्लेख किया है के बारे में _.extend(...) और के लिए आपके वर्तमान ...

+1

मैं बस कहना चाहता हूं कि उपरोक्त पोस्ट किया गया kalimotxocoding.blogspot.com इस मुद्दे को हल नहीं करता है और यह विशेष रूप से भयानक है। मैं इसे जांचने की सिफारिश नहीं करता हूं। –

+1

रीढ़ की हड्डी हैक को न देखें। ऐसा करने का पहला तरीका देखें जहां आपको बच्चे के दृश्य में मूल दृश्य की घटनाओं को स्पष्ट रूप से विस्तारित करना होगा। विस्तृत उत्तर के लिए – PhD

27

एक और विकल्प बेसव्यू होना है जो विस्तार के कार्यान्वयन को ओवरराइड करता है। जैसे:

var BaseView = Backbone.View.extend({ 
     //base view functionality if needed 
    }); 
BaseView.extend = function(child){ 
    var view = Backbone.View.extend.apply(this, arguments); 
    view.prototype.events = _.extend({}, this.prototype.events, child.events); 
    return view; 
}; 

यह बेसव्यू से प्राप्त होने वाली किसी भी चीज़ के लिए स्वचालित रूप से आपके सभी ईवेंट का विस्तार करेगा।

+0

अच्छा समाधान जो व्यवहार को केंद्रीकृत करता है बल्कि इसे अन्य समाधानों की तरह वितरित करता है। – WiredPrairie

+0

बहुत अच्छा। क्या बैकबोन में डिफ़ॉल्ट रूप से ऐसा कोई कारण है? शायद वे अंडरस्कोर के विस्तार() पर अधिक सवारी नहीं करना चाहते थे? – tybro0103

10

मैं श्री शेवर का समाधान चाहते हैं, लेकिन कुछ कम दखल के लिए:

var ChildView = ParentView.extend({ 
    events : _.extend({ 
     "change input": "handleInputChange" 
    }, ParentView.prototype.events) 
}); 

संपादित: हाँ, आप प्रत्येक बच्चे कक्षा में यह करने के लिए है, लेकिन यह उपयोगी है जब केवल कुछ ही बच्चों की जरूरत है , या जब आप अभिभावक "कक्षा" को नियंत्रित नहीं करते हैं।

+0

लेकिन इस बच्चे को प्रत्येक बच्चे के दृश्य के लिए उस कोड को कॉपी और पेस्ट करने की एक ही समस्या है। –

+0

मुझे माता-पिता पर 'जेनेरिक एवेन्ट्स' बनाने के बजाय 'ParentView.prototype.events' के उपयोग को पसंद है।प्रत्येक बच्चे के दृश्य के लिए कॉपी/पेस्टिंग के बिना इसे कैसे करें इसके बारे में मेरा उत्तर देखें। – tybro0103

+0

सहमत हैं, आपका समाधान बेहतर प्रतीत होता है ... हालांकि, अब मैं इसके बारे में सोचता हूं, इस तरह की समस्याओं के बारे में चिंता करने के कारण मुझे जेएस समग्र –

3

यहां एक समाधान है जो मेरे लिए अच्छा काम करता है। आप प्रत्येक सबक्लास में विस्तार किए बिना ईवेंट ऑब्जेक्ट दोनों माता-पिता और उप-वर्ग में उपयोग कर सकते हैं। बस इसे कक्षा कक्षा में एक बार बढ़ाएं:

APP.Views.GenericWizard = Backbone.View.extend({ 
    events: { 
    'click .btn-prev' : function(){} 
    }, 
    initialize: function() { 
    _(this.events).extend(APP.Views.GenericWizard.prototype.events); 
    } 
}); 

APP.Views.RegisterWizard = APP.Views.GenericWizard.extend({ 
    events: { 
    'blur #username' : function(){} 
    }, 
}); 

var registerWizard = new APP.Views.RegisterWizard(); 
console.log(registerWizard.events); 
// Object {blur #username: function, click .btn-prev: function} 
+0

कृपया डाउनवोट के कारण बताएं। क्या यहां कुछ गड़बड़ है? – tybro0103

+0

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

+0

@ क्रिस, अच्छा बिंदु। मेरा तरीका केवल उप-वर्ग के एक स्तर का समर्थन करता है। – tybro0103

संबंधित मुद्दे