9

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

मेरे ऐप अधिक मापनीय मैं हर ClosedTune के लिए घटनाओं चाहते हैं TuneBook को प्रत्यायोजित किया जाना है, लेकिन रख-रखाव के लिए मैं एक ही संचालकों (लोगों Tune में संग्रहीत) TuneBook द्वारा प्रयोग की जाने (हालांकि वे चाहते चाहते हैं बनाने के लिए स्पष्ट रूप से कुछ समारोह में लपेटने की जरूरत है)।

समस्या मेरे पास है

सही ClosedTune खोजने पर हैंडलर कॉल करने के लिए TuneBook भीतर, है। इसे आर्किटेक्ट करने का एक अच्छा तरीका क्या है, या माता-पिता के दृष्टिकोण को ईवेंट देने के लिए अन्य अच्छे समाधान हैं?

नोट - नहीं Backbone View: Inherit and extend events from parent का डुप्लिकेट (एक माता पिता के वर्ग से इनहेरिट बच्चों के बारे में है जो है, जबकि मैं बच्चों जो डोम में माता-पिता के बच्चे नोड्स हैं के बारे में पूछ रहा हूँ)

+0

यदि घटनाओं को 'ट्यून' में हैंडलर द्वारा निष्पादित किया जा रहा है, तो आप 'चाइल्ड व्यू -> पेरेंट व्यू -> मॉडल' को क्यों डालना चाहते हैं .. आप 'ChildViewler' से सीधे 'Model.handler' निष्पादित कर सकते हैं। .. दूसरी तरफ आप 'मॉडल' को मैसेंजर के रूप में उपयोग कर सकते हैं: आप चाइल्ड व्यू से मॉडल की स्थिति को संशोधित कर सकते हैं और पेरेंट व्यू को इस संशोधन को सुन सकते हैं। – fguillen

+0

@fguillen यह घटनाओं को बाध्य करने के लिए बहुत कम कुशल है (शायद मुझे स्पष्ट होना चाहिए कि बैकबोन कस्टम इवेंट्स के बजाए डोम इवेंट्स का मतलब है) प्रत्येक बच्चे के दृश्य के डोम नोड को केवल एक बार पैरेंट व्यू के डोम नोड के बजाय। मेरे ऐप प्रदर्शन द्वारा उत्पन्न 300 पंक्ति तालिका पर प्रत्येक पंक्ति पर सीधे बाध्य करते समय ध्यान से सुस्त होता है। मुझे जो चाहिए वह है 'पेरेंट व्यू -> [childView] -> childModel' – wheresrhys

उत्तर

10

आपके मूल दृश्य में (Backbone.Events से भी विस्तारित), मैं onEvent को डोम ईवेंट में बांध दूंगा। ट्रिगर पर, यह एक रीढ़ की हड्डी की घटना को आग लगाएगा जिसमें कुछ "आईडी" विशेषता शामिल है जिसमें आपके बच्चे के विचार जानते हैं (संभवतः कुछ पंक्ति आईडी?)।

var TuneBook = Backbone.View.extend(_.extend({}, Backbone.Events, { 
    events: { 
     "click .tune .button": "clickHandler" 
    }, 
    clickHandler: function (ev) { 
     this.trigger('buttonClick:' + ev.some_id_attr, ev); 
    }, 

})); 

बाल विचार तब स्वाभाविक रूप से उन माता-पिता दृश्य घटनाओं की सदस्यता लेते हैं जो उन्हें चिंतित करते हैं। नीचे मैं initialize में पैरेंट व्यू को पास करता हूं और साथ ही उस विशेष आईडी विशेषता जिसे आपने options में पहले उपयोग किया था।

var ClosedTune = Backbone.View.extend({ 

    initialize: function (options) { 
     options.parent.on('buttonClick:' + options.id, this.handler, this); 
    }, 

    handler: function (ev) { 
     ... 
    }, 

}); 

आप निश्चित रूप से भी इसी तरह के ग्राहकों Tune या OpenTune पर सेट कर सकते हैं।

+2

यह दृष्टिकोण अभिभावक दृश्य को "ईवेंट एग्रीगेटर" के रूप में उपयोग करता है जो कि पालन करने के लिए एक अच्छा पैटर्न है। वैकल्पिक रूप से, आप एक अलग ऑब्जेक्ट भी बना सकते हैं जो आपका ईवेंट एग्रीगेटर है और इसे अपने बच्चे के विचारों में पास कर दें। फिर आपके बच्चों को सही वस्तु खोजने के लिए डीओएम को पार करने की आवश्यकता नहीं है जिस पर घटनाओं को सुनना है। ईवेंट एग्रीगेटर्स पर अधिक जानकारी के लिए, यह आलेख देखें: http://lostechies.com/derickbailey/2012/04/03/revisiting-the-backbone-event-aggregator-lessons-learned/ –

+0

यह सही दिखता है। आज रात को आजमाएंगे – wheresrhys

+0

मैंने इसे लगभग एकमात्र बदलाव के साथ कार्यान्वित किया, जिसे मैंने 'ट्यूनबुक' की ऐडऑन() विधि में 'क्लोज़ट्यून' के ईवेंट श्रोताओं को अटैचमेंट किया था) ए को संदर्भित करने से बचें बी) उपयोग सक्षम करें अन्य संदर्भों के भीतर 'क्लोज़ड्यून' का – wheresrhys

7

यहां पर कुछ कर रहे हैं संभावनाओं का।

1. केन्द्रीकृत: TuneBook उदाहरण

  1. स्टोर tune_book.tunes में प्रत्येक ClosedTune के लिए एक संदर्भ में दुकान ClosedTune वस्तुओं। आप कैसे tune_book.tunes पॉप्युलेट करते हैं; चूंकि आपने TuneBook पर एक योजक विधि का उल्लेख किया है, जो मैंने नीचे दिखाया है।

  2. TuneBook ईवेंट हैंडलर में, कुंजी के रूप में घटना लक्ष्य की id विशेषता की तरह कुछ का उपयोग करके tune_book.tunes से ClosedTune पुनः प्राप्त। फिर Tune या ClosedTune हैंडलर को कॉल करें।

http://jsfiddle.net/p5QMT/1/

var Tune = Backbone.View.extend({ 
    className: "tune", 

    click_handler: function (event) { 
    event.preventDefault(); 
    console.log(this.id + " clicked"); 
    }, 

    render: function() { 
    this.$el.html(
     '<a href="" class="button">' + this.id + '</a>' 
    ); 

    return this; 
    } 
}); 

var ClosedTune = Tune.extend({}); 

var OpenTune = Tune.extend({ 
    events: { 
    "click .button" : 'click_handler' 
    } 
}); 

var TuneBook = Backbone.View.extend({ 
    events: { 
    "click .tune .button" : 'click_handler' 
    }, 

    click_handler: function (event) { 
    var tune = this.options.tunes[ 
     $(event.target).closest(".tune").attr('id') 
    ]; 

    tune.click_handler(event); 
    }, 

    add_tune: function (tune) { 
    this.options.tunes[tune.id] = tune; 
    this.$el.append(tune.render().el); 
    }, 

    render: function() { 
    $("body").append(this.el); 
    return this; 
    } 
}); 

var tune_book = new TuneBook({ 
    tunes: {} 
}); 

[1, 2, 3].forEach(function (number) { 
    tune_book.add_tune(new ClosedTune({ 
    id: "closed-tune-" + number 
    })); 
}); 

tune_book.render(); 

var open_tune = new OpenTune({ 
    id: "open-tune-1" 
}); 

$("body").append(open_tune.render().el); 

2. विकेन्द्रीकृत: jQuery.data()

  1. का उपयोग कर डोम वस्तु के साथ दृश्य वस्तु से संबद्ध करने पर आप एक ClosedTune बनाने के लिए, यह करने के लिए एक संदर्भ की दुकान है, उदा this.$el.data('view_object', this)

  2. ईवेंट श्रोता में, ClosedTune पुनर्प्राप्त करें, उदा। $(event.target).data('view_object')

तुम, और OpenTune (TuneBook में) ClosedTune लिए एक ही सटीक हैंडलर का उपयोग कर सकते हैं अगर आप चाहते हैं।

http://jsfiddle.net/jQZNF/1/

var Tune = Backbone.View.extend({ 
    className: "tune", 

    initialize: function (options) { 
    this.$el.data('view_object', this); 
    }, 

    click_handler: function (event) { 
    event.preventDefault(); 

    var tune = 
     $(event.target).closest(".tune").data('view_object'); 

    console.log(tune.id + " clicked"); 
    }, 

    render: function() { 
    this.$el.html(
     '<a href="" class="button">' + this.id + '</a>' 
    ); 

    return this; 
    } 
}); 

var ClosedTune = Tune.extend({ 
    initialize: function (options) { 
    this.constructor.__super__.initialize.call(this, options); 
    } 
}); 

var OpenTune = Tune.extend({ 
    events: { 
    "click .button" : 'click_handler' 
    } 
}); 

var TuneBook = Backbone.View.extend({ 
    events: { 
    "click .tune .button": Tune.prototype.click_handler 
    }, 

    add_tune: function (tune) { 
    this.$el.append(tune.render().el); 
    }, 

    render: function() { 
    $("body").append(this.el); 
    return this; 
    } 
}); 

var tune_book = new TuneBook({ 
    tunes: {} 
}); 

[1, 2, 3].forEach(function (number) { 
    tune_book.add_tune(new ClosedTune({ 
    id: "closed-tune-" + number 
    })); 
}); 

tune_book.render(); 

var open_tune = new OpenTune({ 
    id: "open-tune-1" 
}); 

$("body").append(open_tune.render().el); 

टिप्पणी करने के लिए

मैं विकल्प 1 माना जाता है, लेकिन यह के खिलाफ फैसला किया के रूप में मैं पहले से ही Tunebook में धुन मॉडल का एक संग्रह है और किसी अन्य वस्तु मैं नहीं चाहता था कि रिस्पांस डी सिंक में रखने की आवश्यकता

मुझे लगता है कि यह निर्भर करता है कि किस प्रकार की हाउसकीपिंग/सिंकिंग आपको करने की आवश्यकता महसूस करती है, और क्यों।

(उदा। TuneModel.remove() में मुझे ट्यूनबुक की विचारों की सूची से दृश्य को हटाने की आवश्यकता होगी ... शायद इसे करने के लिए ईवेंट की आवश्यकता होगी, इसलिए एक ईवेंट केवल समाधान अधिक आकर्षक दिखने लगता है)।

क्यों आपको लगता है कि आप "दृश्यों का Tunebook की सूची से दृश्य हटाने की जरूरत" लग रहा है? (मैं आपको यह सुझाव नहीं दे रहा हूं कि आपको नहीं करना चाहिए, सिर्फ क्यों आप चाहते हैं।) चूंकि आप करते हैं, तो आप कैसे सोचते हैं कि @ ggozad का दृष्टिकोण उस सम्मान में भिन्न है?

दोनों तकनीक ClosedTuneTuneBook उदाहरण में ऑब्जेक्ट्स स्टोर करती हैं। @ Ggozad की तकनीक में यह सिर्फ एक अमूर्तता के पीछे छिपा हुआ है जो शायद आपको कम स्पष्ट बनाता है।

मेरे उदाहरण में वे एक सादे जे एस वस्तु (tune_book.tunes) में जमा हो रहे हैं। @ Ggozad में वे _callbacks संरचना में संग्रहीत हैं Backbone.Events द्वारा उपयोग की गई संरचना।

जोड़ना एक ClosedTune:

1.

this.options.tunes[tune.id] = tune; 

2.

this.on('buttonClick:' + tune.id, tune.handler, tune); 

आप से छुटकारा पाने चाहते हैं एक ClosedTune (आप tune.remove() साथ दस्तावेज़ से हटाने का कहना है और आप चाहते हैं कि व्यू ऑब्जेक्ट पूरी तरह से चला गया हो), @ ggozad के दृष्टिकोण का उपयोग करके ClosedTune पर अनाथ संदर्भ छोड़ दिया जाएगा I n tune_book._callbacks जब तक आप गृह व्यवस्था की ही तरह है कि दृष्टिकोण मैं सुझाव के साथ मतलब होगा प्रदर्शन:

1.

delete this.options.tunes[tune.id]; 

tune.remove(); 

2.

this.off("buttonClick:" + tune.id); 

tune.remove(); 

प्रत्येक उदाहरण की पहली पंक्ति वैकल्पिक है - अगर आप ClosedTune ऑब्जेक्ट्स को साफ़ करना चाहते हैं या नहीं।

विकल्प 2 कम या ज्यादा अभी मैं क्या कर रहा हूँ, लेकिन (अन्य कारणों के लिए) मैं भी दृश्य पर एक डेटा विशेषता के रूप में मॉडल की दुकान है। $ एल, और मैं महसूस कर रही है कि मदद नहीं कर सकता जगह पर संदर्भ संग्रहीत करने से बेहतर तरीका होना चाहिए।

ठीक है, अंत में यह चीजों को ढूढ़ने के लिए आपकी वरीयता के लिए नीचे आता है। यदि आप व्यू ऑब्जेक्ट्स को अधिक केंद्रीकृत फैशन में संग्रहीत करना पसंद करते हैं, तो आप उन्हें jQuery.data का उपयोग करने के बजाय TuneBook इंस्टेंस में स्टोर कर सकते हैं। देखें # 1: केंद्रीकृत। TuneBook में एक सादे वस्तु में, या TuneBook में _callbacks में jQuery.data का उपयोग कर, या:

एक तरह से या किसी अन्य आप ClosedTune वस्तुओं के लिए संदर्भ भंडारण कर रहे हैं।

यदि आप समझने के कारणों के लिए @ ggozad का दृष्टिकोण पसंद करते हैं, तो इसके लिए जाएं, लेकिन यह जादू नहीं है। जैसा कि यहां प्रस्तुत किया गया है, मुझे यकीन नहीं है कि # 1 में मौजूद अधिक सरल संस्करण की तुलना में अमूर्तता के अतिरिक्त स्तर द्वारा कौन सा लाभ प्रदान किया जाना चाहिए। अगर कुछ फायदा है, तो मुझे भरने में संकोच न करें।

+0

मैंने विकल्प 1 पर विचार किया लेकिन इसके खिलाफ फैसला किया क्योंकि मेरे पास पहले से ही ट्यूनबुक में ट्यून मॉडल का संग्रह है और मैं नहीं चाहता था कि मुझे एक और ऑब्जेक्ट रखना होगा सिंक (उदाहरण के लिए TuneModel.remove() में मुझे ट्यूनबुक की दृश्यों की सूची से दृश्य को हटाना होगा ... शायद इसे करने के लिए ईवेंट की आवश्यकता होगी, इसलिए एक ईवेंट केवल समाधान अधिक आकर्षक दिखने लगता है)। विकल्प 2 अब मैं कम कर रहा हूं, लेकिन (अन्य कारणों से) मैं मॉडल को डेटा एट्रिब्यूट के रूप में भी स्टोर करता हूं। $ El, और मैं यह महसूस करने में मदद नहीं कर सकता कि एक बेहतर तरीका होना चाहिए जगह पर संदर्भ संग्रहीत करने से। – wheresrhys

+0

@wheresrhys मुझे नहीं पता कि यह आपके चयन में एक कारक था, लेकिन मैंने बेवकूफ त्रुटियों को सही किया है जो मेरे पिछले कोड उदाहरणों में थे। मैंने आपकी टिप्पणी के जवाब के साथ अपना जवाब अपडेट किया (देखें "टिप्पणी का जवाब दें" खंड)। – JMM

+0

पूरी तरह उत्तर के लिए चीयर्स। यह सच है कि घटनाओं को एक जादू बुलेट के रूप में देखना आसान है जो कमजोर जोड़ों को बिना किसी डाउनसाइड्स के ऑब्जेक्ट करता है, और आप सही हैं कि वस्तुओं को हटाने के दौरान मुझे कॉलबैक को अस्वीकार करने के लिए और अधिक विचार देना चाहिए। फिर भी घटनाएं अभी भी मेरा पसंदीदा विकल्प है। दूर किए गए विचारों के डुप्लिकेट संदर्भ होने से मुझे या अन्य डेवलपर्स के दुरुपयोग के लिए क्लीनर और कम मोहक लगता है। $ .डेटा का उपयोग करने के लिए मैं हमेशा डीओएम से पूछताछ करने वाले किसी भी चीज का उपयोग करने से सावधान रहता हूं जब तक कि डीओएम इंटरैक्शन अपेक्षाकृत धीमी न हो। – wheresrhys