2014-11-03 91 views
0

的jsfiddle關聯的模型,:http://jsfiddle.net/umgauper/jnf8B/743/Backbone.js的:this.model事件是第一個模型渲染,而不是與DOM元素

我試圖創建一個基本的購物車應用程序。點擊某件商品時,我希望將其標題和價格添加到購物車表中。

我正在爲每個模型創建一個單獨的視圖實例。但是,當單擊某個項目時,添加的表格數據始終是item1模型的模型數據,而不是我期望與單擊的DOM元素關聯的模型數據。爲了獲得點擊元素的模型數據,我需要做些什麼改變?

var app = app || {}; 
 
var Item = Backbone.Model.extend({ 
 
    defaults: { 
 
     order: '', 
 
     title: '', 
 
     price: 0.01, 
 
     inCart: false 
 
      } 
 
}); 
 

 

 
var item1 = new Item({order: 1, title: "shoes", price: 30.00}); 
 
var item2 = new Item({order: 2, title: "socks", price: 5.00}); 
 
var item3 = new Item({order: 3, title: "shirt", price: 20.00}); 
 

 
var ItemsCollection = Backbone.Collection.extend({model: Item}); 
 

 
var items = new ItemsCollection([item1, item2, item3]); 
 

 
app.ItemView = Backbone.View.extend({ 
 
    template: _.template($("#item-template").html()), 
 
    initialize: function() { 
 
     this.render() 
 
    }, 
 
    render: function() { 
 
     $("#display").append(this.template(this.model.attributes)); 
 
    }, 
 
    el: "#container", 
 
    events: { 
 
     'click .title': 'moveToCart' 
 
    }, 
 
    moveToCart: function(e) { 
 
     e.stopImmediatePropagation(); 
 
     var title = this.model.get("title"); 
 
     var price = this.model.get("price"); 
 
     $("table").append("<tr><td>" + title + "</td><td>" + price + "</td></tr>"); 
 
    } 
 
}); 
 

 

 
var itemView1 = new app.ItemView({model: item1}); 
 
var itemView2 = new app.ItemView({model: item2}); 
 
var itemView3 = new app.ItemView({model: item3});
<div id="container"> 
 
    <div id="display"> 
 

 
    </div> 
 
    <table id="cart"> 
 
     <thead> 
 
     <th>Title</th> 
 
     <th>Price</th> 
 
     </thead> 
 

 
    </table> 
 
    </div> 
 
    <script type="text/template" id="item-template"> 
 
    <div> 
 
     <p class="title"><%= title %></p> 
 
     <p class="price">$<%= price %></p> 
 
    </div> 
 
    </script>

回答

0

你的問題是,所有的app.ItemView份額相同el

app.ItemView = Backbone.View.extend({ 
    //... 
    el: "#container", 

和事件通過代表團綁定到el。結果就是你的事件都被混淆了,因爲每個人都試圖在同一個元素上聽同一個事件。

最簡單的解決方案是將<div>搬出你的#item-template模板:

<script type="text/template" id="item-template"> 
    <p class="title"><%= title %></p> 
    <p class="price">$<%= price %></p> 
</script> 

,並使其成爲elItemView。如果您沒有以任何其他方式指定el,主幹視圖會創建一個空的<div>作爲其el,因此您可以從ItemView刪除el聲明。你想也需要調整render佔新結構:

render: function() { 
    this.$el.append(this.template(this.model.toJSON())); 
    $('#display').append(this.el); 
    return this; 
} 

return thisrender到底是標準的做法,這樣你可以說這樣的話:

$x.append(view.render().el); 

移動$('#display').append(...)調出一個級別也是常見的,並有助於保持視圖的獨立性。另外請注意,我切換到this.model.toJSON()而不是this.model.attributes;假裝attributes不存在通常是一個好主意,這樣你就不會意外地將Backbone背後的東西混淆了。

更新小提琴:http://jsfiddle.net/ambiguous/cad0kxee/

+0

啊哈!現在你已經指出了,似乎每個視圖都應該有自己的el。謝謝你的幫助!並提醒在渲染中添加'return this'語句。 – unamaga 2014-11-03 19:41:53

0

Here是你的任務的另一種實現方式。

我想你已經很清楚,用相同的el選擇器初始化很多Backbone.View是不好的做法。

我在執行我已經分居項目視圖和容器視圖,以便您將有:

app.ContentView = Backbone.View.extend({ 
    template: _.template($("#item-template").html()), 
    render: function() { 
     this.$el.append(this.template(this.model.attributes)); 
     return this; 
    }, 
    events: { 
     'click .title': 'moveToCart' 
    }, 
    moveToCart: function(e) { 
     e.stopImmediatePropagation(); 
     var title = this.model.get("title"); 
     var price = this.model.get("price"); 
     $("table").prepend("<tr><td>" + title + "</td><td>" + price + "</td></tr>"); 
    } 

}); 

和「的CollectionView」

app.ContentsView = Backbone.View.extend({ 
    initialize: function() { 
     this.render() 
    }, 
    render: function() { 
     var that = this; 
     this.buffer = document.createDocumentFragment(); 
     this.collection.each(function(model){ 
      var itemView = new app.ContentView({model: model}); 
      that.buffer.appendChild(itemView.render().el); 
     }); 
     this.$el.append(this.buffer); 
    }, 
    el: "#display" 
}); 

我猜你會添加的項目/產品集合動態,而不是一個一個,這種方法將是有幫助的。請注意,我在此處使用了documentFragment進行緩存。

另一注意事項:如果您決定使用Backbone來實現應用程序/單頁應用程序,則還需要嘗試Backbone.Marionette。它會爲你自動化很多員工,並且會節省很多時間。希望這可以幫助。

+0

我看到,如果我需要添加大量項目,您的解決方案會更好。謝謝!感謝關於木偶的小貼士 - 我會研究它。 – unamaga 2014-11-03 19:53:49

+0

'this.collection.each(function(model){...},this)'會比'that'和'_.each(collection,...)'搞亂,不是嗎?你可能想檢查你的'_.each'回調實際上是否已經通過,'_.each(collection,...)'和'collection.each(...)'不是完全一樣的東西。 – 2014-11-03 20:13:51

+0

@ muistooshort - 當然,_each(collection,...)和collection.each(...)是不同的。在小提琴中的JS代碼的末尾,你會發現我將集合作爲骨幹模型的數組傳遞,所以爲什麼我使用了第一個版本。在Backbone.Collection的情況下,我們需要使用第二個。 – 2014-11-03 20:55:49

相關問題