2012-07-09 81 views
2

Noob here學習backbone.js。我試圖創建一個簡單的水平菜單(每個菜單項是一個模型,整個菜單是一個集合)。我想知道哪個菜單項被點擊。在menuItemView中,我將「click a」事件綁定到「clicked」函數,但點擊時它不會觸發。我最接近的解決方案,我發現在:http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/,我試圖複製類似的功能...即使我認爲我已經複製它幾乎相同,我仍然似乎無法讓它的工作。我確實瀏覽了所有似乎解決檢測哪個模型/項目被點擊的問題的帖子,但他們似乎都沒有幫助。任何幫助,將不勝感激。我知道一個可點擊的菜單並獲取它的id可能在簡單的jquery中更直接,但我想我會以此爲例來學習骨幹。Backbone.js:點擊時訪問特定項目

HTML

<header> 
<ul id="nav"> 
</ul> 
</header> 

JAVASCRIPT

(function($) { 

window.app = window.app || {}; 

//Goal:if selected=true, menu item should be highlighted 
MenuItem = Backbone.Model.extend({ 
    label: "Default Label", 
    selected: false, 
    id: 0 
}); 

MenuList = Backbone.Collection.extend({ 
    model: MenuItem, 
    initialize: function(models, options) { 
     //nothing ... yet 
    } 
}); 


//View for a single item. Returns el that looks like: 
// <li id='4' class='false'><a href='#4'> Item 4 </a> </li? 
MenuItemView = Backbone.View.extend({ 
    tagName: "li", 

    render: function() { 
     var id = this.model.get("id"); 
     var cls = this.model.get("selected"); 
     var lbl = this.model.get("label"); 
     $(this.el).attr('id', id).addClass(cls.toString()); 
     $(this.el).html("<a href=#" + id + " >" + lbl + "</a> </li>"); 
     return this; //recommended as this enables calls to be chained. 
    }, 

    events: { 
     "click a": "clicked" //Firebug shows 'a' element bound to 
          //native 'click' and not 'clicked'. WHY? 
    }, 

    clicked: function(ev){ 
     alert($(ev.target).text()); //NOT HAPPENING :-(
     //do something to highlight menu item via css stuff. 
    } 
}); 

MenuListView = Backbone.View.extend({ 
    el: $("header > ul"), 

    initialize: function() { 
     this.menulist = new MenuList(null, { view: this }); 
     _.bindAll(this, "renderItem"); 
    }, 

    renderItem: function(model) { 
     var menuitemView = new MenuItemView({ model: model }); 
     menuitemView.render(); 
     $(this.el).append(menuitemView.el); 
    }, 

    render: function() { 
     this.collection.each(this.renderItem); 
    }, 

    setActivePage: function(ev) { 
     alert($(ev.target).text()); 
     window.app.footerview.updatePageNumber(10); 
    } 
}); 


var items = new MenuList([ 
{id: 1, label: "item 1", selected: true}, 
{id: 2,label: "item 2",selected: false}, 
{id: 3,label: "item 3",selected: false}, 
{id: 4,label: "item 4",selected: false} 
]); 


window.app.menuview = new MenuListView({ collection: items }); 
window.app.menuview.render(); 
$("header").html(window.app.menuview.el); 

})(jQuery); 

這種情況的運行例子可以的jsfiddle可以看出:..看http://jsfiddle.net/gopal_a/4uzcb/3/

回答

0

你的問題就在這裏:

$("header").html(window.app.menuview.el); 

window.app.menuview.el已經在DOM,因爲你已經這樣定義它:

el: $("header > ul") 

當你$('header').html(...),你清理掉什麼是已經在<header>,然後用你的el代替它;但是,您的.html()調用會殺死Backbone安裝的事件委託者來處理視圖上的事件。結果是,你最終在DOM中使用了正確的HTML,但是你沒有附加任何事件處理。

刪除您的$("header").html(window.app.menuview.el),事情就會開始起作用。

另外,您不必說$(this.el),骨幹視圖已定義this.$el,因此您可以使用this.$el來代替。

+0

太棒了...很好的解釋和感謝您的幫助。我不明白JS中的事件處理很好,但我想我已經從中得到了更多的理解。我總是懷疑$(this.el)和this。$ el之間的區別。很高興知道它們是同一件事。 – 2012-07-10 05:36:21

+0

@GA:通常'x.html(v.el)'沒問題,問題是'v.el'已經在'x'裏面了,「把它拿出來放回去」 。 – 2012-07-10 06:08:11