2011-12-22 13 views
17

हम सभी जानते हैं कुछ इस तरह कर रही है बुरा है:Backbone.js में उप विचारों को घटनाओं सौंपना

<ul> 
    <li>Item</li> 
    <li>Item</li> 
    ... 500 more list items 
</ul> 

और फिर ...

$("ul li").bind("click", function() { ... }); 

मैं एक बहुत माध्यम से देख रहा है बैकबोन उदाहरण/गाइड का और निम्नलिखित मॉडलों के संग्रह के आधार पर वस्तुओं के साथ एक सूची प्रस्तुत करने के लिए एक मानक दृष्टिकोण प्रतीत होता है।

var ListView = Backbone.View.extend() { 

    tagName: 'ul', 

    render: function() { 
    this.collection.each(function(item) { 
     var view = new ListItemView({model: item}); 
     $(this.el).append(view.render().el); 
    }); 
    return this; 
    } 
}); 

एक सूची आइटम दृश्य:

var ListItemView = Backbone.View.extend() { 

    tagName: 'li', 

    events: { 
    'click' : 'log' 
    } 

    log : function() { 
    console.log(this.model.get("title")); 
    } 

    render: function() { 
    $(this.el).html(this.template(this.model.toJSON())); 
    return this; 
    } 
}); 

अगर मैं गलत नहीं हूँ, 500 मॉडल के साथ एक संग्रह के साथ ListView instantiating, मुझे 500 क्लिक घटनाओं, हर पंक्ति में एक देता है। यह बुरा है?

मैं जानता हूँ कि रीढ़ namespaced घटनाओं के लिए घटना प्रतिनिधिमंडल में बनाया गया है:

events : { 
    'click li' : 'log' 
} 

मैं मैं अपने ListView में इस डाल सकता है लगता है, और यह केवल पूरी सूची के लिए एक क्लिक घटना बन जाएगा, लेकिन फिर मैं wouldn क्लिक किए गए सूची आइटम से संबंधित मॉडल डेटा तक पहुंच प्राप्त करने में सक्षम नहीं होगा।

रीडबोन डेवलपर्स इस विशिष्ट समस्या को हल करने के लिए किस पैटर्न का उपयोग करते हैं?

उत्तर

9

Derick बेली इस दुविधा के बारे में एक विस्तृत ब्लॉग पोस्ट में लिखा है, आप इसे बाहर यहाँ देख सकते हैं: http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/

+0

धन्यवाद, यह उस तरह की चर्चा थी जिसे मैं ढूंढ रहा था। – Daniel

2

तुम इतनी तरह एक तत्व के साथ उदाहरण संबद्ध कर सकते हैं:

events : { 
    'click li' : 'log' 
}, 

log: function(e) { 
var elm = e.currentTarget //Same as `this` in normally bound jQuery event 


jQuery.data(elm, "viewInstance").log(e); 
}, 

तब:

var ListItemView = Backbone.View.extend() { 

    tagName: 'li', 

    log : function() { 
    console.log(this.model.get("title"); 
    } 

    render: function() { 
     //Associate the element with the instance 
    $(this.el).html(this.template(this.model.toJSON())).data("viewInstance", this); 
    return this; 
    } 
}); 
+1

आपके उत्तर के लिए धन्यवाद। इस तरह की समस्या के आसपास काम करने के लिए मुझे यह करना है, लेकिन फिर, यह डीओएम में डेटा स्टोर करने के लिए jQuery का उपयोग कर रहा है, लंबे समय तक एक बहुत साफ दृष्टिकोण की तरह महसूस नहीं करता है। – Daniel

+1

@ डैनियल वेल jQuery डीओएम में डेटा स्टोर नहीं करता है, यह इसे नियमित जेएस ऑब्जेक्ट ('jQuery.cache') में संग्रहीत करता है। jQuery भी किसी भी तत्व को आंतरिक रूप से प्रदूषित करता है जिसमें किसी भी विस्तारित संपत्ति के साथ ईवेंट (ओं) होता है, जिसके बाद तत्व पर 'डेटा' करने से नियमित जेएस ऑब्जेक्ट में अधिक गुण जोड़ने के अलावा कोई प्रभाव नहीं पड़ता है। – Esailija

+0

आह ठीक है। अच्छा मुझे लगता है कि तब काम की तरह होगा। धन्यवाद – Daniel

3

अभिभावक दृश्य से सबव्यू का ट्रैक रखें। फिर सबव्यूव जोड़ते समय इसे हैश में जोड़ें और साथ ही सबव्यू के एल को सिड जोड़ें। इस तरह सबव्यू के लिए एक सूचक है और इसके मॉडल आदि पर संचालन कर सकता है ...

मैंने नीचे इस सटीक कोड का परीक्षण नहीं किया है, इसलिए यह एक या दो जगहों में गलत हो सकता है लेकिन मैंने इस सामान्य सिद्धांत का परीक्षण किया है। मैंने listitemview कोड भी छोड़ा है।

var ListView = Backbone.View.extend() { 
    subViews: {}, 
    tagName: 'ul', 
    events: { 
    'click li' : 'clickItem' 
    }, 
    clickItem: function(event){ 
    var id = event.currentTarget.cid; 
    var subView = this.subViews[id]; 


    }, 
    render: function() { 

    this.collection.each(function(item) { 
     var view = new ListItemView({model: item}); 
     this.subViews[view.cid] = view; 
     subEl = view.render().el; 
     subEl.cid = view.cid; 
     $(this.el).append(subEl); 
    }); 
    return this; 
    } 
});