2011-12-22 26 views
17

Hepimiz böyle bir şey yaptığını kötü olduğunu biliyorum: o zamanbackbone.js alt görüşlere olayları temsilciliği

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

ve ...

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

ben çok aracılığıyla arıyordum Omurga örneklerinin/kılavuzlarının ve aşağıdakilerin bir liste koleksiyonundan yola çıkılarak bir listenin bir liste oluşturulmasında standart bir yaklaşım olduğu görülmektedir.

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; 
    } 
}); 

listesi öğesi görünümü: Ben yanılmıyorsam

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 modelleriyle koleksiyonu ile ListView başlatmasını, bana 500 tıklama olayları, her satır için bir tane verir. Bu kötü değil mi?

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

benim ListView bu koyabiliriz ve tek tam liste için tek tıklama olayını yaratacak, ama sonra ben olacak:

bildiğim Omurga isim alanlı olayları için olay heyette inşa etti Tıklanan liste öğesine karşılık gelen model verilerine erişme.

Omurga geliştiricileri bu tipik sorunu çözmek için hangi kalıpları kullanır?

Sen şöyle bir eleman ile örneğini ilişkilendirebileceğiniz

cevap

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); 
}, 

Ardından:

Derick Bailey bu ikilem hakkında detaylı blog yazısı yazdı
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

Cevabınız için teşekkür ederiz. Bu, şu ana kadar bu soruna geçici bir çözüm bulmak için yapmak zorunda olduğum bir şeydi, ama sonra tekrar, DOM'da veri depolamak için jQuery kullanıyor, uzun vadede çok temiz bir yaklaşım gibi hissetmiyor. – Daniel

+1

@Daniel Well jQuery verileri DOM'de saklamıyor, normal bir js nesnesinde ('jQuery.cache') saklıyor. jQuery ayrıca dahili olarak bir expando özelliğine sahip olan herhangi bir unsuru da kirletir, daha sonra eleman üzerinde 'data' yapmanın normal js nesnesinde daha fazla özellik eklemekten başka bir etkisi yoktur. – Esailija

+0

Ah Tamam. Sanırım bu bir çeşit iş olurdu. teşekkürler – Daniel

3

Ardından, alt görünümü eklerken kareyi eklemeye ekler ve ayrıca alt göstergenin elkiine eki ekleyin. Bu şekilde alt göstergeye bir işaretçi var ve onun modeli üzerinde operasyonlar gerçekleştirebiliyorlardı ...

Bu tam kodu aşağıda test etmedim, bu yüzden bir yerde iki yanlış olabilir, fakat bu genel prensibi test ettim. Listitemview kodunu da ihmal ettim.

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; 
    } 
});