Backbone.js:执行Fetch()后,只渲染新模型

时间:2012-09-29 19:46:31

标签: javascript jquery backbone.js underscore.js

我有一个集合App.listingList,后面的fetch()会被add:true调用。

App.listingList.fetch({
        data: {some:data},
        processData: true,
        add: true
});

问题:新添加的模型如何渲染其视图,而无需重新渲染现有模型的视图。这意味着我做不到:

this.collection.each( function(listing, index) {
    new ListingMarkerView({ model:listing }).render();
}, this);

尝试#1

在集合的add事件中呈现视图,我无法找到一种方法来访问要渲染的新模型

ListingListView = Backbone.View.extend({

    initialize: function() {
        this.collection.bind('add', this.renderNew, this);
    },

    render: function() {
        console.log('render ListingListView');
        this.collection.each( function(listing, index) {
            new ListingMarkerView({ model:listing }).render();
        }, this);
        return this;
    },

    renderNew: function() {
        // How do I grab the new models?
        new ListingMarkerView({ model:listing }).render(); // wont work
        return this;
    }
});

尝试#2

我尝试使用第二个Collection来执行后续fetch,并使用underscore.js' s _.without()比较两个集合的模型,但返回的数组仍然包含找到的元素在作为参数传递的第二个数组中。使用_difference()也返回了与第一个数组一样传递的相同数组。

App.listingListNew.fetch({
        data: {some:data},
        processData: true,
        success: function() {
            console.log(App.listingListNew.models);
            console.log(App.listingList.models);
            console.log(_.without(App.listingListNew.models, App.listingList.models));
            console.log(_.difference(App.listingListNew.models, App.listingList.models));
        }
});

console.log输出

由于我将2个相同的数组传入_.difference()_.without(),因此输出应为[]。但它不是:/也许因为cid不同,所以每一个都被视为唯一?

enter image description here

2 个答案:

答案 0 :(得分:5)

执行collection.bind('add', this.renderNew, this);时,它会自动将添加的模型作为参数传递给您的方法。

在您的方法中包含参数,您应该可以访问新模型。

renderNew: function(newModel) {
    new ListingMarkerView({ model:newModel }).render();
    return this;
}

答案 1 :(得分:0)

我知道这是一个老问题,但我遇到了同样的问题并遇到了这个问题,所以我想我会添加一个替代方法。我不确定它有多高效,但它确实有效。我正在使用它来支持无限滚动功能。

我正在使用Backbone 1.2.1,因此在集合提取中,我使用remove:false而不是每个文档中已弃用的add:truehttp://backbonejs.org/#Collection-fetch

基本方法是在首次渲染时对集合中的每个项目设置rendered属性为true,然后使用该属性忽略后续渲染中先前渲染的项目。

模特和收藏:

MyApp.Item = Backbone.Model.extend({});

MyApp.ItemList = Backbone.Collection.extend({
model: MyApp.Item,
    url: '/api/item/',
    parse : function(response){
        if (response.stat) {
            return _.map(response.content, function(model, id) {
                model.id = id;
                return model;
            });
        }
    }
});

查看:

MyApp.ItemListView = Backbone.View.extend({
    tagName: 'ul',
    className: 'item-list',
    render: function() {
        this.collection.each(function(item){
            //don't render items that have already been rendered!
            if (!item.rendered) {
                var itemListDetailView = new MyApp.ItemListDetailView({model: item});
                this.$el.append(itemListDetailView.render().el);
                item.rendered = true;
            }
        }, this)
        return this;
    }
});

MyApp.ItemListDetailView = Backbone.View.extend({
    tagName: 'li',
    className: 'item-list-detail',
    render: function() {
        $(this.el).html( '<div class="item-title">' + this.model.get('title') + '</div>');
        return this;
    }
});

获取功能:

MyApp.loadMyItems = function () {
    MyApp.gettingData = true;  //flag for infinite scroll
    MyApp.myItems.fetch({
        traditional: true,
        remove:false,
        data: {
            u_id: MyApp.User.id,
            order: 'create_date:desc',
            start: MyApp.myItems.length,
            num_items: 10
        },
        success: function(){
           MyApp.gettingData = false; //flag for infinite scroll
           MyApp.myItemsView.render();
        }
    });
};

通话:

//on initial page load
MyApp.myItems = new MyApp.ItemsCollection();
MyApp.myItemsView = new MyApp.ItemListView({
                            collection: MyApp.myItems, 
                            el: $('#my-items') 
                         });
MyApp.loadMyItems();

//infinite scroll
$('#items .infinite-scroll').on('loadmore', function () {
    if (!MyApp.gettingData) {
        MyApp.loadMyItems();
    } 
});