Domanda

Questo è il mio primo tentativo di utilizzare Backbone.js, così ho deciso di fare una semplice applicazione di test che simula un menu di un ristorante con le voci di menu. Stavo seguendo insieme a questo raffreddare post sul blog da andyet.net .

Sto avendo un problema quando si aggiunge un modello a un insieme. Ho legato un metodo al fine di evento add della collezione che dovrebbe aggiornare la vista. Ecco il codice con tanto di codice irrilevante rimosso il più possibile.

(nota: ho tolto le cose come le dichiarazioni portata var locali e chiusure per brevità Quanto segue è ancora un po 'lungo, e so che è fastidioso, ma dovrebbe essere abbastanza semplice e facile da capire.) :

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);
});  

Ho segnato con i commenti della zona problematica. Secondo il Backbone Documentazione :

Se jQuery o Zepto è incluso nella pagina, ogni vista ha una funzione che gestisce $ query scope all'interno dell'elemento della vista.

Quindi, se sto impostando this.menuList = this.$('#menuList'); nel metodo di rendering, perché non posso accedere this.menuList nel metodo addMenuItem? La demo che ho legato alla in cima vuol exacly come questo. Inoltre, se io scambiare this.menuList per un selettore jQuery, in questo modo:

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

Tutto funziona bene. Ma non lo faccio vuole per selezionare nuovamente l'ID MenuList viene eseguito ogni volta addMenuItem. Il Rightway TM is alla cache dopo che si è reso.

Si noti inoltre:. Ho pensato che forse il problema era con il modello ICanHaz non tornare abbastanza veloce, ma poi this.menuList sarebbe un array vuoto, non undefined, in modo che di no

È stato utile?

Soluzione

Si sta eseguendo nella # 1 Gotcha con JavaScript - la ristretta dinamicamente this parola chiave. Quando si tira fuori this.addMenuItem come riferimento, senza vincolante, la funzione addMenuItem perde la sua nozione di this. Ci sono due semplici modi per risolvere il problema nel codice, sostituire questa riga:

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

Con questa:

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

o aggiungere questa linea alla parte superiore della vostra funzione di inizializzazione, che compirà effettivamente la stessa cosa:

_.bindAll(this, 'addMenuItem');

Altri suggerimenti

Probabilmente metodo addMenuItem sia chiamato prima rendering metodo viene chiamato e quindi la definizione di MenuList manca nella addMenuItem.

Perché non si preme this.menuList = questo $ ( '# MenuList');. a inizializzazione metodo e provare

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top