Backbone.js | Как я могу сохранить элементы вида для поиска позже?

StackOverflow https://stackoverflow.com/questions/4542433

Вопрос

Это моя первая попытка использовать Backbone.js, поэтому я решил сделать простое тестовое приложение, которое имитирует меню ресторана с пунктами меню. Я следил за этот классный пост в блоге от andyet.net.

У меня проблема при добавлении модели в коллекцию. Я связал метод представления с событием добавления коллекции, который должен обновить представление. Вот код с удаленным как можно большим неуместным кодом.

(Примечание: я удалил такие вещи, как локальная область var Декларации и закрытие ради краткости. Следующее еще немного длинное, и я знаю, что это раздражает, но это должно быть довольно просто и легко понять):

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

Я пометил комментариями проблемную область. Согласно Документация на основе:

Если jQuery или Zepto включено на страницу, в каждом представлении есть функция $, которая запускает запросы, приведенные в элементе представления.

Итак, если я настраиваю this.menuList = this.$('#menuList'); В методе рендеринга, почему я не могу получить доступ this.menuList в addMenuItem метод? Демонстрация, с которой я связал наверху, делает это так же, как это. Кроме того, если я поменяю this.menuList Для селектора jQuery, как так:

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

Все работает нормально. Но я не делаю хочу Чтобы заново выбирать идентификатор менлистов каждый раз addMenuItem выполнено. Правильный путьТМ это кэшировать его после того, как он отображается.

Также примечание: я подумал, что, возможно, проблема была с шаблоном Icanhaz, недостаточно быстро, но потом this.menuList был бы пустым массивом, а не undefined, так что это не так.

Это было полезно?

Решение

Вы сталкиваетесь с #1 Gotcha с JavaScript - динамически this ключевое слово. Когда ты снимаешь this.addMenuItem в качестве ссылки без привязки, addMenuItem Функция теряет свое представление о this. Анкет Есть два простых способа исправить его в вашем коде, либо замените эту строку:

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

С этим:

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

Или добавьте эту строку в верхнюю часть вашей функции инициализации, которая будет эффективно выполнять то же самое:

_.bindAll(this, 'addMenuItem');

Другие советы

Вероятно, метод addmenuitem вызывается до вызова метода рендеринга, и, следовательно, определение для меналиста отсутствует в AddMenuitem.

Почему бы тебе не толкнуть this.menulist = this. $ ('#Menuist'); к инициализировать Метод и попробуйте?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top