Backbone.js我应该何时何地获取我的收集数据?

时间:2014-03-05 21:27:04

标签: javascript backbone.js backbone-views backbone-routing backbone-collections

我对实例化集合的时间和地点感到有点困惑,并在骨干应用程序中获取它们。

我已经看到它现在已经完成了几个方面,并且在我非常简单的小CRUD联系人管理器应用程序中工作了我很乱,但我确信有一些约定和'陷阱'我不是意识到了。

这些是我看过的选项,要么已经开始工作,要么就是“工作”了:)选项4似乎是概念上最好的,但是我把它搞砸了。

糟糕的想法:1)在我真正对路由器做任何事情之前,我实例化了一个新的集合并调用了fetch,然后在doc ready语句中启动了app.view。

    // Create an Instance of the collection
    App.contacts = new App.Collections.Contacts;

    App.contacts.fetch({update: true, remove: false}).then(function() {
        new App.Views.App({ collection : App.contacts });
    });
  • 这很有效 - 但如果我在应用程序中有多个集合,它似乎不是真的正确的方式,我认为这个想法失败了。

BAD IDEA:2)当我开始使用路由器时,我想在路由器init方法中做同样的事情,这也很有用,但我认为这给我留下了同样的问题。

坏想法:3)我尝试在集合中使用init方法,虽然我在很多地方读过这个但这个想法很糟糕。

好想法(?):但我不能让它工作:4)我想,当我实例化它的View时,获取集合的数据是有意义的,这样如果我有一个联系人集合和一个任务集合,当我在路由器中实例化它的视图时,每个集合都只会从服务器中取出。这对我来说似乎是一个成功的公式,但是当我试图将它放在View init或渲染方法中时,我this.collection.on('add', this.addOne, this);给了我不能调用.on on undefined。 (注意:我试过把它放在成功函数中)

我正在努力,请帮助。

干杯。

编辑:附加代码,以便我们可以诊断下面讨论的双重负载。

在我的路由器文件中,我正在使用此实用程序obj:

var ViewManager = {
    currentView : null,
    showView : function(view) {
        if (this.currentView !== null && this.currentView.cid != view.cid) {
            this.currentView.remove();
        }
        this.currentView = view;
        return view;
    }
}

在我的路由器中:我在路线上调用此方法

list: function() {
    console.log('backbone loading list route');

    var AllContactsView = new App.Views.Contacts({ //init method runs now
        collection : App.contacts
    });

    ViewManager.showView(AllContactsView);

},

我的收藏

App.Collections.Contacts = Backbone.Collection.extend({
    model: App.Models.Contact,
    url: 'contacts',
});

在我看来

App.Views.Contacts = Backbone.View.extend({
    tagName: 'tbody',

    initialize: function() {

            this.listenTo(this.collection, 'sync', this.render);
            this.listenTo(this.collection, 'add', this.addOne);

        this.collection.fetch({
            // update: true,
            // remove: false
        });

    },

    render: function() {
        // append the list view to the DOM
        $('#allcontacts').append(this.el);

        // render each of the single views
        this.collection.each( this.addOne, this);
        return this;
    },

    addOne: function(contact) {
        var contactView = new App.Views.Contact({ model: contact});
        this.$el.append(contactView.render().el);
    }

});

在我的app.js

// Run App
jQuery(document).ready(function($) {

    // Create an Instance of the collection
    App.contacts = new App.Collections.Contacts;

    // Init BB Router
    new App.Router.Route;
    Backbone.history.start(); // Kick it all off.

});

4 个答案:

答案 0 :(得分:1)

您的观点应该是这样的:

App.Views.Contacts = Backbone.View.extend({
    tagName: 'tbody',

    initialize: function() {

        this.listenTo(this.collection, 'reset', this.render);
        this.listenTo(this.collection, 'add', this.addOne);

        vent.on('contactR:closeAll', this.closeView, this);

        this.collection.fetch();
    },
});

答案 1 :(得分:0)

所以我实现了我的错误,因为那个讨厌的小this关键词melarky,所以现在它是一个风格或概念性的问题

可能在我的设置文件中调用路由器之前。

App.contacts = new App.Collections.Contacts;

在我的路由器中:

list: function() {
    var AllContactsView = new App.Views.Contacts({
        collection : App.contacts
    });

    ViewManager.showView(AllContactsView);

},

在视图中:

App.Views.Contacts = Backbone.View.extend({
    tagName: 'tbody',

    initialize: function() {
        var that = this;
        this.collection.fetch({ update: true, remove: false}).then(function() {
            that.collection.on('add', that.addOne, that);
            vent.on('contactR:closeAll', that.closeView, that);
            that.render();
        });


    },
});

这对我来说似乎更灵活,在概念上对我来说更合适,但我会喜欢这个答案的反馈。

答案 2 :(得分:0)

因此,似乎让render方法中的.each有点无意义,因为在fetch连接成功并且在触发sync事件之前,add事件会触发。因此,add事件的listenTo会在需要时触发addOne,而render事件现在只是将集合附加到dom同步。

App.Views.Contacts = Backbone.View.extend({
tagName: 'tbody',

initialize: function() {

        this.listenTo(this.collection, 'sync', this.render);
        this.listenTo(this.collection, 'add', this.addOne);

    this.collection.fetch();

},

render: function() {
    // append the list view to the DOM
    $('#allcontacts').append(this.el);

    /* 
     render each of the single views - removing this seems to set everything 
     right in the world
   */

   // this.collection.each( this.addOne, this);
    return this;
},

addOne: function(contact) {
    var contactView = new App.Views.Contact({ model: contact});
    this.$el.append(contactView.render().el);
}

});

答案 3 :(得分:0)

因此经过大量的谷歌搜索,阅读和测试后,我已经完成了以下工作。我不认为这是最优的,因为我们迫使主干运行其重置事件,这似乎是在大多数示例应用程序中完成它的方式,虽然我觉得这忽略了默认行为已更改的事实,当然这是有原因的吗?

最终这种方法目前有效,但我会非常高兴看到另一种选择。

/*Collection view
- - - - - - -*/
App.Views.Contacts = Backbone.View.extend({
    tagName: 'tbody',
    initialize: function() {
          this.listenTo(this.collection, 'add', this.addOne);
          this.listenTo(this.collection, 'reset', this.addAll);
          this.listenTo(this.collection, 'all', this.render);
          this.collection.fetch({reset:true});
    },
    render: function() {
        // append the list view to the DOM
        $('#allcontacts').append(this.el);
        return this;
    },
    addAll : function() {
        this.collection.each( this.addOne, this);
    },
    addOne: function(model) {
        var contactView = new App.Views.Contact({ model: model});
        this.$el.append(contactView.render().el);
    }
});

我有这个实用程序,我已将调用添加回到:

var ViewManager = {
    currentView : null,
    showView : function(view) {
        if (this.currentView !== null && this.currentView.cid != view.cid) {
            this.currentView.remove();
        }
        this.currentView = view;
        return view.render();
    }
}

在我的路由器中,我在列表路径上调用它:

list: function() {
    console.log('backbone loading list route');

    var AllContactsView = new App.Views.Contacts({ //init method runs now
        collection : App.contacts
    });

    ViewManager.showView(AllContactsView);

},

正如我所说,我觉得可能会有一两个小问题,但它现在可以在我的应用程序中运行,我将在稍后阶段再次回到它。无可争议。