Frage

Dies ist mein erster Versuch, Backbone.js zu verwenden. Daher habe ich mich für eine einfache Testanwendung entschieden, die ein Restaurantmenü mit Menüpunkten simuliert. Ich folgte mit Dieser coole Blog -Beitrag von Andyet.net.

Ich habe ein Problem, wenn ich ein Modell zu einer Sammlung hinzufüge. Ich habe eine Ansichtsmethode an das Add -Ereignis der Sammlung gebunden, mit dem die Ansicht aktualisiert werden sollte. Hier ist der Code mit so viel irrelevantem Code wie möglich.

(Hinweis: Ich habe Dinge wie den lokalen Bereich entfernt var Erklärungen und Schließungen aus Kürze. Das Folgende ist noch ein wenig lang, und ich weiß, dass das ärgerlich ist, aber es sollte ziemlich einfach und leicht zu verstehen sein):

MenuItem = Backbone.Model.extend({
    // initialize functions removed for brevity
});
Menu = Backbone.Model.extend({
    // initialize functions removed for brevity
    // MenuSelection property is defined here.
});
MenuSelection = Backbone.Collection.extend({ model: MenuItem });
MenuItemView = Backbone.View.extend({
    // render template
});

/**
 * This is unaltered from the code.  The error occurs here.
 */
RestaurantAppView = Backbone.View.extend({
    addMenuItem : function (MenuItem) {
        var view = new MenuItemView({ model : MenuItem });
        this.menuList.append(view.render().el);
        // ERROR occurs here.  error: "this.menuList is undefined"
    },
    initialize : function () {
        this.model.MenuSelection.bind('add', this.addMenuItem);
    },
    render : function () {
        $(this.el).html(ich.app(this.model.toJSON()));
        this.menuList = this.$('#menuList'); // IT IS DEFINED HERE
        return this;
    }
});

/**
 * Everything after this I left in just-in-case you need to see it.
 */
RestaurantAppController = {
    init : function (spec) {
        this.config = { connect : true };
        _.extend(this.config, spec);
        this.model = new Menu({
           name : this.config.name,
        });
        this.view = new RestaurantAppView({ model : this.model });
        return this;
    }
};
$(function() {
    // simulating ajax JSON response.
    var json = {
        Menu : {
            name : 'Appetizers',
            MenuItem : [
                {
                    name : 'toast',
                    description : 'very taosty',
                    price : '$20.00'
                },
                {
                    name : 'jam',
                    description : 'very jammy',
                    price : '$10.00'
                },
                {
                    name : 'butter',
                    description : 'very buttery',
                    price : '$26.00'
                }
            ]
        }
    };
    window.app = RestaurantAppController.init({
        name : json.Menu.name
    });
    $('body').append(app.view.render().el);
    app.model.MenuSelection.add(json.Menu.MenuItem);
});  

Ich habe mit Kommentaren den problematischen Bereich markiert. Nach dem Backbone -Dokumentation:

Wenn JQuery oder Zepto auf der Seite enthalten ist, verfügt jede Ansicht über eine $ -Funktion, in der Abfragen ausgelegt werden, die im Element der Ansicht verteilt sind.

Also, wenn ich setze this.menuList = this.$('#menuList'); Warum kann ich in der Render -Methode nicht zugreifen? this.menuList in dem addMenuItem Methode? Die Demo, mit der ich oben verlinkt habe, macht sie so vergrößert. Auch wenn ich auszehne this.menuList Für einen JQuery -Selektor wie SO:

addMenuItem : function (MenuItem) {
    var view = new MenuItemView({ model : MenuItem });
    $('#menuList').append(view.render().el);
}

Alles funktioniert gut. Aber ich nicht wollen Jedes Mal die Menuist-ID neu auszuwählen addMenuItem wird ausgeführt. Der richtige WegTm ist es nach dem Rendern zu rendern.

Hinweis auch: Ich dachte, vielleicht war das Problem bei der Icanhaz -Vorlage, die nicht schnell genug zurückkehrt, aber dann this.menuList wäre ein leeres Array, nicht undefined, Das ist es nicht.

War es hilfreich?

Lösung

Sie rennen mit JavaScript in die Nr. 1 Gotcha - die dynamisch abgeschöpften this Stichwort. Wenn Sie abziehen this.addMenuItem Als Referenz ohne Bindung, die, die addMenuItem Funktion verliert ihren Begriff von this. Es gibt zwei einfache Möglichkeiten, es in Ihrem Code zu beheben, entweder diese Zeile ersetzen:

this.model.MenuSelection.bind('add', this.addMenuItem);

Mit diesem:

this.model.MenuSelection.bind('add', _.bind(this.addMenuItem, this));

Oder fügen Sie diese Zeile an die Spitze Ihrer Initialisierungsfunktion hinzu, die effektiv dasselbe erreicht:

_.bindAll(this, 'addMenuItem');

Andere Tipps

Wahrscheinlich wird die AddMenuitem -Methode aufgerufen, bevor die Render -Methode aufgerufen wird, und daher fehlt die Definition für die Menulistin im AddMenuitem.

Warum drückst du nicht? this.menulist = this. $ ('#Menulist'); zu initialisieren Methode und versuchen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top