Backbone Model Ids和点击事件

时间:2014-07-11 17:43:48

标签: backbone.js

好的。我打算在这里放弃并寻求帮助。我想我遇到了多个问题而且不确定最好的方法。我正在使用把手创建一个我的json对象的骨架模型。现在模板工作我想点击获取模型,以便能够添加到另一个集合。

我的第一个问题。我认为骨干默认定义了一个模型ID?如果我将默认设置为“”或null,则每个模型的id为“”或null。 json对象有一个我可以分配给主干id的id,但是如果我在默认的id:jsonID中这样做,则jsonID是未定义的。如果我在控制台中执行object.toJSON(),则没有创建主干的id。所以我没有在把手模板中使用的值来将我的div id分配给该模型的骨干ID。然后使用它来获取元素id,以便在单击时我可以获得骨干ID。或者至少我已经阅读了很多以这种方式做到的例子。

我的第二个问题,我认为源于requirejs。我看到的所有单击的例子甚至使用this.collection或this.model。在我的View文件中,那些总是返回undefined,假设这是因为requirejs。我特别尝试了这个例子http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/。我想知道我是否应该使用requirejs废弃,它似乎会导致更多问题然后帮助。

到目前为止,这是我的代码,我删除了我的点击功能代码,因为它没有工作。

收集档案:

define(['jquery', 'backbone', 'lodash', 'Models/GroceryItem'],

    function($, Backbone, _, GroceryItem) {

    var GroceryItems = Backbone.Collection.extend({

        model: GroceryItem,

        url: "data.json",

        parse: function(response) {
            return response.all_coupons;

        }

    });

    var storeItems = new GroceryItems();
    storeItems.fetch({
    success:function(){
        console.log(storeItems.toJSON());
        }
    });

    return storeItems;

});

查看文件:

define(['jquery', 'backbone', 'lodash', 'handlebars', 'Collections/GroceryItems'],

    function($, Backbone, _, Handlebars, storeItems) {



    var GroceryItemsView = Backbone.View.extend({

        template: Handlebars.compile(
            '<ul class="d-row">' +
                    '{{#each storeItems}}' +
                        '<li class="lineItem" id="{{coupon_id}}">' +    
                            '<div class="wrapper">' +
                                '<div class="header">{{coupon_title}}</div>' +              
                                    '<div class="column_wrapper">' +
                                        '<div class="two-col">' +
                                            '<div class="product_image"><img src="{{coupon_thumb}}" alt="{{coupon_description}}" height="110" width="110"></div>' +
                                            '<div class="description">{{coupon_description}}</div>' +
                                         '</div>' +
                                    '</div>' +
                                '<div class="expiration">Valid From: {{valid_from}} to {{valid_to}}</div>' +    
                            '</div>' +
                        '</li>' +
                '{{/each}}' +
            '</ul>'
            ),

        events: {
            "click li": "getModel"
        },

        getModel:function(e){

        },

        render: function() {
            var that = this;
            storeItems.fetch({
                success: function(storeItems) {
                    var storeTemplate = that.template({storeItems: storeItems.toJSON()});
                    that.$el.html(storeTemplate);
                    return that;
                }
            })          
            return this; 
        }
    });

    return GroceryItemsView;

});

非常感谢帮助。非常感谢。如果我完全错了,我会接受任何建议。我只是在学习骨干和javascript,所以当我用大量的谷歌搜索时,我正在磨砺。

谢谢!

编辑代码:

define(['jquery', 'backbone', 'lodash', 'Collections/GroceryItems', 'Views/GroceryItemView'],

    function($, Backbone, _, storeItems, GroceryItemView) {

    var GroceryItemsView = Backbone.View.extend({

        tagName: 'ul',
        className: 'd-row',
        el: '#container',
        initialize: function () {
            //basically says only render when collection syncs
            this.listenTo(storeItems, 'sync', this.render);
        },

        render: function () {
            //got keep track of views for when you need close them (not important for now but you'll thank me later)
            this.groceryItemsView = [];
            storeItems.each(function (GroceryItem) {
                //we are making a new view for each model and passing it in as an option
                var itemView = new GroceryItemView({
                    model: GroceryItem
                });
                //The view creates an element but it is not attached to DOM. We will attach it to the ItemsView's $el (which IS attached to the DOM)
                this.$el.append(itemView.$el);

                this.groceryItemsView.push(itemView);
            }, this);
            }
        });

    var list = new GroceryItemsView();

    return list;

});

define(['jquery', 'backbone', 'lodash', 'handlebars', 'Views/GroceryItemsView', 'Models/GroceryItem'],

    function($, Backbone, _, Handlebars, GroceryItemsView, GroceryItem) {

        var GroceryItemView = Backbone.View.extend({

        template: Handlebars.compile(
            '<div class="wrapper">' +
                '<div class="header">{{coupon_title}}</div>' +
                    '<div class="column_wrapper">' +
                        '<div class="two-col">' +
                            '<div class="product_image"><img src="{{coupon_thumb}}" alt="{{coupon_description}}" height="110" width="110"></div>' +
                            '<div class="description">{{coupon_description}}</div>' +
                        '</div>' +
                    '</div>' +
                '<div class="expiration">Valid From: {{valid_from}} to {{valid_to}}</div>' +
            '</div>'
        ),

        tagName: 'li',

        className: 'lineItem',

        events: {
            'click': 'getModel'
        },

        initialize: function () {
           this.render();
        },

        getModel: function () {
            return this.model;
        },

        render: function () {
            this.$el.html(this.template(this.model.toJSON()));
        }
    });

    return GroceryItemView;
});

2 个答案:

答案 0 :(得分:1)

在骨干模型中实际上有两种id,第一种是id,它用于表示模型在服务器上的id,并且不是原子分配的。第二个是cid(客户端ID),主干将以原子方式生成并为您分配。

如果您的服务器模型的id属性未命名为id,则可以通过设置idAttributemodel属性来映射它。例如,如果json模型中的id被称为 jsonID

var GroceryItems = Backbone.Collection.extend({

    model: GroceryItem,
    idAttributemodel: jsonID,

    url: "data.json",

    parse: function(response) {
        return response.all_coupons;

    }

});

有关id, cid, idAttribute

的更多信息

我在你的GroceryItems集合文件中看到你是声明你的集合并实例化它,在这种情况下更有意义的是声明它并返回你的应用程序视图(或任何地方)你声明你的集合视图)在那里实例化它并将它传递给视图。

为了在li的点击事件中检索模型ID,您必须选择每个li的单独视图,该视图绑定到特定模型,或者在您的如果您使用相同的视图渲染所有模型,则可以从DOM中检索它。

例如

 getModel: function (e) {
        //you might want to consider using data attributes instead
        var modelId = $(e.currentTarget).attr('id'); 
        var model = this.storeItems.get(modelId);
    },

一般来说,关于使用require.js,我认为虽然从长远来看有一点学习曲线但值得。您可能要考虑做的一件事是为每个视图/模型/集合保留一个文件。

答案 1 :(得分:0)

获取所点击内容模型的最简单方法非常简单。

  1. 我强烈建议不要依赖ID。这是非常糟糕的做法。使用模型的重点是停止担心ID:P
  2. 创建骨干视图并不像有些人说的那么昂贵。只要你正确清理,它实际上非常有效。将DOM的每个逻辑单元分解为自己的View。特别是意见集合
  3. 要求很棒。不要放弃它。一旦你搞清楚了,你就永远不想回去了。只需将其视为从另一个文件中保存一堆代码到顶部定义的变量
  4. 请勿使用success选项。只收听sync事件。使代码更清晰,防止以后出现奇怪问题。
  5. 我还没有测试过这段代码,但逻辑有效(多次完成)

    //Preferrably keep this in a separate file or use require-handlebars
    var itemTpl = Handlebars.compile(
        '<div class="wrapper">' +
        '<div class="header">{{coupon_title}}</div>' +
        '<div class="column_wrapper">' +
        '<div class="two-col">' +
        '<div class="product_image"><img src="{{coupon_thumb}}" alt="{{coupon_description}}" height="110" width="110"></div>' +
        '<div class="description">{{coupon_description}}</div>' +
        '</div>' +
        '</div>' +
        '<div class="expiration">Valid From: {{valid_from}} to {{valid_to}}</div>' +
        '</div>');
    
    //Your Collection
    var GroceryItems = Backbone.Collection.extend({
    
        model: GroceryItem,
    
        url: "data.json",
    
        parse: function (response) {
            return response.all_coupons;
        }
    
    });
    
    //This Represents all your views
    var ItemsView = Backbone.View.extend({
        tagName: 'ul',
        el: '.where-this-is-supposed-to-go',
        initialize: function () {
            this.collection = new GroceryItems();
            //basically says only render when collection syncs
            this.listenTo(this.collection, 'sync', this.render);
        },
    
        render: function () {
            //got keep track of views for when you need close them (not important for now but you'll thank me later)
    
            this.itemViews = [];
            this.collection.each(function (m) {
                //we are making a new view for each model and passing it in as an option
                var itemView = new ItemView({
                    model: m
                });
    
                //The view creates an element but it is not attached to DOM. We will attach it to the ItemsView's $el (which IS attached to the DOM)
                this.$el.append(itemView.$el);
    
                this.itemViews.push(itemView);
            }, this);
        }
    });
    
    var ItemView = Backbone.View.extend({
        template: itemTpl,
        tagName: 'li',
        className: 'lineItem',
        events: {
            'click': 'getModel'
        },
        initialize: function () {
           this.render();
        },
        getModel: function () {
            //it's already there. No IDs
            return this.model;
        },
        render: function () {
            this.$el.html(this.template(this.model.toJSON()));
        }
    });
    
相关问题