【问题标题】:Backbone.js Where and When should I fetch my collection data?Backbone.js 我应该在何时何地获取我的收藏数据?
【发布时间】:2014-03-05 21:27:04
【问题描述】:

我对何时何地实例化集合并在主干应用程序中获取它们感到有些困惑。

我现在已经看到它以几种方式完成,并且在我非常简单的小型 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 });
    });
  • 这行得通 - 但如果我要在一个应用中拥有多个集合,这似乎不是正确的方法,我认为这个想法失败了。

坏主意:2)当我开始使用路由器时,我想在路由器初始化方法中执行与上述相同的操作,这也有效,但我认为给我留下了同样的问题。

坏主意:3)我尝试在集合 init 方法中获取,尽管我在很多地方读到这似乎是一个坏主意。

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

这让我很头疼,请帮忙。

干杯。

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

在我的路由器文件中,我使用了这个实用程序 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.

});

【问题讨论】:

  • 从上面的代码看不出集合为什么会被调用两次,可以加App.Collections.Contacts代码吗?
  • 完成了,但我不这么认为。

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


【解决方案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();
    },
});

【讨论】:

  • cool 是的,这很好,很花哨,我已经表达了上面注入集合非常酷,但这并不清楚 - 获取的地点和时间, - 我的假设在视图中,当它被路由器实例化时,-想法?
  • 很好,很好, - 有点意思,希望您能在下面对我的想法提供反馈。
  • 我更喜欢那个 - 很好,如果你删除前半部分,我会将它标记为正确,因为它只有后半部分回答了问题。
  • 现在的问题是,首先,我没有收到重置事件,通过更改它同步我得到了结果,但是它然后加载了两次集合。
  • sync 在集合收到来自服务器的响应时触发,reset 在重置其状态时触发,如果您传递update: true,则不会触发reset 事件。所以你是对的。你给collection.fetch()打了两次电话吗?
【解决方案2】:

所以我意识到了我的错误,因为那个讨厌的小 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();
        });


    },
});

这对我来说似乎更灵活,在概念上对我来说更正确,但我希望得到有关此答案的反馈。

【讨论】:

  • 请注意,虽然我认为上面的@Ridas 解决方案更干净,但它工作得很好。
【解决方案3】:

因此,在 render 方法中添加 .each 似乎毫无意义,因为 add 事件会在 fetch 连接成功之后触发 sync 事件之前触发。所以 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);
}

});

【讨论】:

  • 删除它也是失败的,因为稍后尝试重新实例化视图 - 添加新视图或编辑视图后,视图不会明显呈现。
【解决方案4】:

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

目前这最终可行,但我会非常高兴看到替代方案。

/*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);

},

正如我所说,我觉得这可能存在一两个小问题,但它目前在我的应用程序中有效,毫无疑问我会在稍后阶段再次回到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2017-10-11
    相关资源
    最近更新 更多