Pregunta

Este es mi primer intento de usar Backbone.js, así que decidí hacer una prueba sencilla aplicación que simula un menú de un restaurante con elementos de menú. Estaba siguiendo junto con este enfriar entrada de blog de andyet.net .

Estoy teniendo un problema al añadir un modelo a una colección. He atado un método a fin de añadir evento de la colección que debe actualizar la vista. Aquí está el código de la mayor cantidad de código irrelevante retira como sea posible.

(nota: me quita cosas como declaraciones alcance var locales y cierres en aras de la brevedad El siguiente es todavía un poco de tiempo, y sé que es molesto, pero debe ser bastante sencillo y fácil de entender.) :

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

He marcado con los comentarios de la zona problemática. Según la Documentación Backbone :

Si jQuery o Zepto está incluido en la página, cada vista tiene una función que ejecuta consultas $ ámbito de aplicación dentro elemento de la vista.

Por lo tanto, si estoy estableciendo this.menuList = this.$('#menuList'); en el método render, ¿por qué no puedo acceder a this.menuList en el método addMenuItem? La demo que unido a la parte superior lo hace exacly como este. También, si intercambiar this.menuList para un selector de jQuery, así:

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

Todo funciona bien. Pero no lo hago desee para volver a seleccionar el ID menulist se ejecuta cada vez addMenuItem. El RightWay TM es decir a la caché después de que se dicte.

También tenga en cuenta:. Pensé que tal vez el problema estaba en la plantilla ICanHaz no vuelve lo suficientemente rápido, pero luego this.menuList sería una matriz vacía, no undefined, por lo que de verdad

¿Fue útil?

Solución

Usted está ejecutando en el Problema nº 1 con JavaScript - el ámbito dinámico this palabra clave. Cuando se salga this.addMenuItem como una referencia sin unión que, la función addMenuItem pierde su noción de this. Hay dos maneras fáciles de fijar en su código, reemplace esta línea:

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

Con esta:

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

o añadir esta línea a la parte superior de su función de inicialización, que logrará efectivamente lo mismo:

_.bindAll(this, 'addMenuItem');

Otros consejos

Probablemente método addMenuItem se está llamando antes de rendir método se llama y por lo tanto la definición de MenuList no se encuentra en el addMenuItem.

¿Por qué no se presiona this.menuList = esta $ ( '# MenuList.');? initialize método y tratar

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top