Backbone.js: доступ к конкретному элементу при нажатии

Нуб тут учится backbone.js. Я пытался создать простое горизонтальное меню (каждый пункт меню - это модель, а все меню - это коллекция). Я хотел бы знать, какой пункт меню был нажат. В menuItemView я связываю событие "click a" с функцией "clicked", но оно не срабатывает при нажатии. Самое близкое решение, которое я нашел, было по адресу: http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/ и я попытался воспроизвести подобное функциональность... хотя я думаю, что я скопировал его почти так же, я все еще не могу заставить его работать. Я просмотрел все посты, которые, кажется, касались проблемы определения, на какую модель / элемент нажали, но ни одна из них, похоже, не помогла. Любая помощь будет оценена. Я знаю, что интерактивное меню и получение его идентификатора, вероятно, намного проще в простом jquery, но я подумал, что воспользуюсь этим в качестве примера для изучения магистрали.

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/

1 ответ

Решение

Ваша проблема прямо здесь:

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

Ваш window.app.menuview.el уже в DOM, так как вы определили это так:

el: $("header > ul")

Когда ты $('header').html(...) вы очищаете то, что уже в <header> а затем заменить его своим el; но твой .html() call уничтожает делегаты событий, которые устанавливает Backbone для обработки событий в представлениях. В результате вы получаете правильный HTML-код в DOM, но к ним не привязана обработка событий.

Оставь свой $("header").html(window.app.menuview.el) и все начнет работать.

Как в стороне, вам не нужно говорить $(this.el), Магистральные представления уже есть this.$el определены, так что вы можете использовать this.$el вместо.

Другие вопросы по тегам