Question

Ceci est ma première tentative d'utiliser Backbone.js, alors j'ai décidé de faire une application de test simple qui simule un menu de restaurant avec des éléments de menu. Je suivais avec ce refroidir blog de andyet.net .

Je vais avoir un problème lors de l'ajout d'un modèle à une collection. Je suis lié une méthode en vue de l'événement ajouter de la collection qui devrait mettre à jour la vue. Voici le code le plus de code non pertinent supprimé possible.

(note: je retire des choses comme des déclarations SCOPE var locales et des fermetures pour des raisons de concision qui suit est encore un peu de temps, et je sais que c'est ennuyeux, mais il devrait être assez simple et facile à comprendre.) :

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

J'ai marqué des commentaires de la zone problématique. Selon le Documentation Backbone :

  

Si jQuery ou Zepto est inclus sur la page, chaque vue a une fonction de $ que les requêtes runs scope au sein de l'élément de la vue.

Donc, si je suis la mise en this.menuList = this.$('#menuList'); dans la méthode render, pourquoi puis-je pas accès this.menuList dans la méthode addMenuItem? La I démonstration liée au haut-t-il exacly comme ça. De plus, si j'échange sur this.menuList pour un sélecteur jQuery, comme suit:

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

Tout fonctionne très bien. Mais je ne sais pas veulent sélectionner à nouveau l'ID menulist chaque addMenuItem temps est exécuté. Le RightWay TM est-à cache après qu'il est rendu.

A noter également:. Je pensais que le problème était avec le modèle ICanHaz ne revient pas assez vite, mais this.menuList serait un tableau vide, pas undefined, de sorte que ce pas

Était-ce utile?

La solution

Vous êtes en cours d'exécution dans le # 1 Gotcha avec JavaScript - le mot-clé this scope dynamiquement. Lorsque vous tirez hors this.addMenuItem comme référence sans le liant, la fonction addMenuItem perd sa notion de this. Il y a deux façons simples de le fixer dans votre code, remplacez cette ligne:

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

Avec ceci:

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

Ou ajoutez cette ligne en haut de votre fonction initialize, ce qui permettra d'accomplir efficacement la même chose:

_.bindAll(this, 'addMenuItem');

Autres conseils

Probablement la méthode addMenuItem est appelée avant de rendre la méthode est appelée et donc la définition de MenuList manque dans le addMenuItem.

Pourquoi ne pas vous pousser this.menuList = $ this- ( '# MenuList'). initialize méthode et essayer

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top