backbone fetch collection on page load

2019-03-21 11:26发布

i know that backbone doc says fetch should not be used to populate collections on page load,and i kind of figure out why:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',
    initialize:function(){
        this.fetch();
    },

});

var homeView = Backbone.View.extend({
    el:'#content',
    initialize:function(){
        this.collection = new appCollection(appModel)
        this.render()   

    },
    render: function () {
        var that = this;
        alert(1);
        _.each(this.collection.models, function (item) {
            that.renderApp(item);
         }, this);


    },

    renderApp: function (item) {
        var appview = new appView({
            model: item
        });

        this.$el.append(appview.render().el);
    }
})
 var home = new homeView();

the homeview.render function actually get called before the collection fetched, so when i remove the alert(1); my app wont get rendered, and i get some error says "appname"(template) is undefined.

any idea how to do this?

the fetch method comes really handy and i dont mind to wait for a few second,actually i was intend to show a progress bar indicating that the page is initializing because i got lots of other thing to download,so is it possible to use fetch and when the collection is actually fetched then tha code continue to run???

1条回答
SAY GOODBYE
2楼-- · 2019-03-21 12:01

Let's take this from the beginning:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',
    initialize:function(){
        this.fetch();
    },

});

I would avoid fetching inside initialize. Creating an instance of an appCollection should not necessitate fetching. So use:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',    
});

Then,

var homeView = Backbone.View.extend({
    el:'#content',
    initialize:function(){
        this.collection = new appCollection(appModel)
        this.render()   

    },
    render: function () {
        var that = this, p;
        console.log('fetching...');
        p = this.collection.fetch();
        p.done(function () {
            console.log('fetched!');
            _.each(that.collection.models, function (item) {
                that.renderApp(item);
            }, that);
        });
    },

    renderApp: function (item) {
        var appview = new appView({
            model: item
        });

        this.$el.append(appview.render().el);
    }
})
var home = new homeView();

This allows you to render your homeView and when the collection has been fetched, it will render its models. If you do not understand what p.done does, have a look at jQuery's Deferred. In brief an ajax request returns a promise. When the promise is fulfilled (i.e. your collection is fetched) the deferred fires and whatever function you specified in .done() will execute. Use the points where I console.log to give feedback on the progress.

查看更多
登录 后发表回答