2012-03-06 16 views
6

क्या कोई नया मॉडल आइटम backbone.js Collection के बीच में डालने का एक सीधा तरीका है और फिर सही स्थिति में नया आइटम शामिल करने के लिए संग्रह के View को अद्यतन करें?किसी आइटम को backbone.js संग्रह में सम्मिलित करना

मैं किसी सूची से आइटम जोड़ने/हटाने के लिए नियंत्रण पर काम कर रहा हूं। प्रत्येक सूची आइटम का अपना Model और View है, और मेरे पास पूरे संग्रह के लिए View भी है।

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

संग्रह में आइटम डालने से सीधा था, लेकिन मुझे संग्रह दृश्य को अपडेट करने का तरीका पता लगाना मुश्किल हो रहा है। मैं कुछ इस तरह की कोशिश कर दिया गया है:

ListView = Backbone.View.extend({ 
    el: '#list-rows', 
    initialize: function() { 
     _.bindAll(this); 
     this.collection = new Items(); 
     this.collection.bind('add', this.addItem); 
     this.render(); 
    }, 
    render: function() { 
     this.collection.each(this.addItems); 
     return this; 
    }, 
    addItem: function (item) { 
     var itemView = new ItemView({ model: item }), 
      rendered = itemView.render().el, 
      index = this.collection.indexOf(item), 
      rows = $('.item-row'); 

     if (rows.length > 1) { 
     $(rows[index - 1]).after(rendered); 
     } else { 
     this.$el.append(rendered); 
     } 
    } 
} 

इस कार्यान्वयन तरह का काम कर रहा है, लेकिन मैं अजीब कीड़े हो रही है जब मैं एक नया आइटम जोड़ने। मुझे यकीन है कि मैं उनको हल कर सकता हूं, लेकिन ...

मेरे सिर में एक आवाज है जो मुझे बताती है कि ऐसा करने का एक बेहतर तरीका है। मैन्युअल रूप से यह पता लगाने के लिए कि नया ItemView कहां डालना है वास्तव में हैकी - संग्रह दृश्य को पहले से संग्रह को पुन: प्रस्तुत करने के बारे में नहीं पता होना चाहिए?

कोई सुझाव?

उत्तर

4

सामान्य तरीके से मैं कर रहा हूं ListView फ़ंक्शन में प्रत्येक ItemView प्रस्तुत करें। तब मैं सिर्फ render कार्य करने के लिए add घटना बाँध, इस तरह:

ListView = Backbone.View.extend({ 
    el: '#list-rows' 
    , initialize: function() { 
    _.bindAll(this); 
    this.collection = new Items(); 
    this.collection.bind('add', this.render); 
    this.render(); 
    } 
    , render: function() { 
    this.$el.empty(); 
    var self = this; 
    this.collection.each(function(item) { 
     self.$el.append(new ItemView({ model: item }).render().el); 
    }); 
    return this; 
    } 
} 

हर आप this.collection.add(someModel, {at: index}) फोन, देखने तदनुसार फिर से रेंडर किया जाएगा।

+0

मुझे इसे काम करने के लिए 'रेंडर' विधि के अंदर '(.item-row) .remove()' में एक कॉल जोड़ना पड़ा, लेकिन यह एक अच्छा समाधान है। (अन्यथा पुन: प्रस्तुत किए गए आइटम मौजूदा प्रस्तुत वस्तुओं के अंत में जोड़े जा रहे थे।) सहायता के लिए धन्यवाद! –

+0

ओह, आप संग्रह के माध्यम से लूपिंग करने से पहले '$ el' को साफ़ करने के लिए' el.empty() 'कर सकते हैं :) – sntran

+0

यह ठीक है कि मैं वर्तमान में संग्रह में आइटम कैसे जोड़ रहा हूं। यह संग्रह में सही जगह पर नया आइटम डाल रहा है।मैंने देखा कि मेरे ऊपर उपरोक्त मेरी टिप्पणी में कुछ टाइपो हैं: मैं '$ ('। Item-row ') को कॉल कर रहा हूं। संग्रह को अंतिम बार बनाए गए आइटम को साफ़ करने के लिए हटाएं() '। यह सिर्फ दृश्य को रीसेट कर रहा है। इसके बारे में सोचने के लिए आओ, एक 'रीसेट' विधि है जो मैं चाहता हूं जो कर सकता है। मैं उसे कॉल करने का प्रयास करूंगा और फिर 'रेंडर' कहूंगा। –

9

मुझे नहीं लगता कि नया तत्व जोड़ते समय पूरे संग्रह को पुन: प्रस्तुत करना सबसे अच्छा समाधान है। यह सही जगह पर नई वस्तु डालने से धीमा है, खासकर अगर सूची लंबी है।

इसके अलावा, निम्नलिखित परिदृश्य पर विचार करें। आप अपने संग्रह में कुछ आइटम लोड करते हैं, और फिर आप n और आइटम जोड़ते हैं (मान लें कि उपयोगकर्ता "अधिक लोड करें" बटन क्लिक करता है)। ऐसा करने के लिए आप विकल्पों में से एक के रूप में add: true पास करने वाली fetch() विधि को कॉल करेंगे। चूंकि डेटा सर्वर से वापस प्राप्त होता है, 'एड' ईवेंट n बार निकाल दिया जाता है और आप अपनी सूची n बार फिर से प्रस्तुत करना समाप्त कर देंगे।

मैं वास्तव में अपने प्रश्न में कोड का एक संस्करण का उपयोग कर रहा है, यहाँ 'जोड़ें' घटना के लिए मेरी कॉलबैक है:

var view, prev, prev_index; 
view = new ItemView({ model: new_item }).render().el; 
prev_index = self.model.indexOf(new_item) - 1; 
prev = self.$el.find('li:eq(' + prev_index + ')'); 
if (prev.length > 0) { 
    prev.after(view); 
} else { 
    self.$el.prepend(view); 
} 

तो, अनिवार्य रूप से मैं सिर्फ :eq() jQuery चयनकर्ता का उपयोग कर रहा बजाय हो रही आपके द्वारा किए गए सभी तत्वों को कम स्मृति का उपयोग करना चाहिए।

+0

यह बहुत अच्छा काम करता है, लेकिन मैं सूची में प्रत्येक आइटम के बगल में नंबर प्रदर्शित कर रहा हूं, इसलिए मुझे संख्याओं को सिंक में रखने के लिए पुनः प्रस्तुत करना होगा। उसके चारों ओर किसी भी तरह से नहीं देख सकते हैं। बमर .... मुझे सादगी पसंद है। – byron

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