2012-07-09 42 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