2011-12-22 259 views
17

我們都知道做這樣的事情是不好的:事件委託給子視圖Backbone.js的

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

然後......

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

我一直在尋找通過大量Backbone示例/指南和以下內容似乎是一個基於模型集合來呈現項目列表的標準方法。

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

如果我沒有記錯,實例化的ListView與500款集合,給了我500個點擊事件,每行一個。這是不好的權利?

我知道骨幹已建成事件代表團命名空間的事件:

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

我想我可以把這個在我的ListView,它只會造成整個列表點擊事件,但後來我不會無法訪問與點擊的列表項目對應的模型數據。

骨幹開發人員用什麼模式解決這個典型問題?

回答

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將數據存儲在DOM中,從長遠來看,感覺不像是一個非常乾淨的方法。 – Daniel 2011-12-22 12:22:28

+1

@Daniel jQuery不會將數據存儲在DOM中,它會將其存儲在常規js對象('jQuery.cache')中。 jQuery還內部污染了具有expando屬性的事件的任何元素,然後在元素上執行'data'除了在常規js對象中添加更多屬性之外沒有任何效果。 – Esailija 2011-12-22 12:24:56

+0

啊好的。那麼我想那樣會有點工作。謝謝 – Daniel 2011-12-22 12:28:06

3

跟蹤父視圖的子視圖。然後,當添加子視圖時,將其添加到散列中,並將該cid添加到子視圖的el中。這種方式有一個指向子視圖,並可以在其模型等執行操作...

我還沒有測試下面這個確切的代碼,所以這可能是錯誤的地方或兩個,但我已經測試了這個一般原則。我也省略了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; 
    } 
});