最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Backbone.js: After doing Fetch(), render only the new models - Stack Overflow

programmeradmin2浏览0评论

I have a Collection App.listingList where subsequent fetch() are called with add:true.

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

Problem: How can the newly added models have their views rendered, without re-rendering the views of the existing models. This means I cannot do:

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

Attempt #1

Rendering the View on the collection's add event, I cannot figure out a way to access the new models to render

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

Attempt #2

I tried having a second Collection to do the subsequent fetch on, and pare the models of both collections using underscore.js's _.without(), but the array returned still contains the elements found in the 2nd array passed as the parameter. Using _difference() also returned the same array passed as the first array.

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 Output

Since I passed in 2 identical arrays into _.difference() and _.without(), the output should be []. But it isnt :/ Maybe because cid is different, so every one of them are treated as unique?

I have a Collection App.listingList where subsequent fetch() are called with add:true.

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

Problem: How can the newly added models have their views rendered, without re-rendering the views of the existing models. This means I cannot do:

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

Attempt #1

Rendering the View on the collection's add event, I cannot figure out a way to access the new models to render

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

Attempt #2

I tried having a second Collection to do the subsequent fetch on, and pare the models of both collections using underscore.js's _.without(), but the array returned still contains the elements found in the 2nd array passed as the parameter. Using _difference() also returned the same array passed as the first array.

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 Output

Since I passed in 2 identical arrays into _.difference() and _.without(), the output should be []. But it isnt :/ Maybe because cid is different, so every one of them are treated as unique?

Share Improve this question edited Sep 29, 2012 at 19:58 Nyxynyx asked Sep 29, 2012 at 19:46 NyxynyxNyxynyx 63.9k163 gold badges507 silver badges856 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

When you do a collection.bind('add', this.renderNew, this); it automatically passes the added model to your method as an argument.

Include the argument in your method and you should have access to the new model.

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

I know this is an old question, but I was having the same issue and came across this response so I thought I'd add an alternate approach. I'm not sure how efficient it is, but it works. I'm using this to support an infinite scroll feature.

I'm using Backbone 1.2.1, so in the collection fetch, I'm using remove:false instead of the deprecated add:true per the docs here: http://backbonejs/#Collection-fetch

The basic approach is to set a rendered attribute to true on each item in the collection when first rendered, then use that to ignore previously rendered items on subsequent fetches.

Model and Collection:

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

Views:

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

Fetch function:

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

Calling:

//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();
    } 
});
发布评论

评论列表(0)

  1. 暂无评论