Backbone.js |如何存储视图元素以便以后检索?

时间:2010-12-27 22:55:18

标签: javascript jquery view undefined backbone.js

这是我第一次尝试使用Backbone.js,所以我决定制作一个简单的测试应用程序来模拟带有菜单项的餐馆菜单。我跟着this cool blog post from andyet.net一起关注。

将模型添加到集合时遇到问题。我已经将一个视图方法绑定到应该更新视图的集合的add事件。这是代码,尽可能多地删除不相关的代码。

(注意:为了简洁起见,我删除了本地范围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);
});  

我在评论中标出了有问题的区域。根据{{​​3}}:

  

如果页面中包含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时,我都不会想要重新选择menulist ID。 RightWay TM 是在渲染后对其进行缓存。

另请注意:我认为问题可能是ICanHaz模板返回的速度不够快,但this.menuList将是一个空数组,而不是undefined,所以不是它。

2 个答案:

答案 0 :(得分:8)

您正在使用JavaScript - 动态范围的this关键字遇到#1陷阱。当您将this.addMenuItem作为引用而不绑定它时,addMenuItem函数会失去this的概念。有两种简单的方法可以在代码中修复它,或者替换这一行:

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

有了这个:

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

或者将此行添加到初始化函数的顶部,这将有效地完成同样的事情:

_.bindAll(this, 'addMenuItem');

答案 1 :(得分:0)

可能在调用render方法之前调用addMenuItem方法,因此addMenuItem中缺少menuList的定义。

为什么不将 this.menuList = this。$('#menuList'); 推送到初始化方法并尝试?