这是我第一次尝试使用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);
}

一切正常。但是我没有 每次重新选择Menulist ID addMenuItem 被执行。正确的方式TM值 在渲染后将其缓存。

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

有帮助吗?

解决方案

您正在使用JavaScript进入#1陷阱 - 动态范围 this 关键词。当你拉开 this.addMenuItem 作为没有约束的参考, addMenuItem 功能失去其概念 this. 。有两种简单的方法可以在代码中修复它,要么替换此行:

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

有了这个:

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

或将此行添加到您的初始化功能的顶部,这将有效地完成相同的事情:

_.bindAll(this, 'addMenuItem');

其他提示

在调用渲染方法之前,可能会调用add -menuitem方法,因此在AddMenuitem中缺少Menulist的定义。

你为什么不推 this.menulist = this。$('#menulist');初始化 方法和尝试?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top