骨干路由器:等待首先获取数据

时间:2011-10-19 14:06:00

标签: routes logic backbone.js

我认为我不太了解正确使用Backbone路由器背后的想法。这就是我所拥有的:

我有一些数据,我在页面加载时从服务器获取数据,然后将其打包到模型和集合中。这些模型和集合的数量是无限的。我想使用路由器直接从一开始就呈现某个集合的视图。

问题是:Backbone路由器提前启动,因为我要求它访问某个视图并触发其render操作,所以它不能这样做,因为这些视图尚未创建。这意味着我实际上必须在获取完成后启动我的路由。

我不知道这是否是一种正确的方法,但我想出的唯一想法是:

  1. 将路由定义和Backbone.history.start();位包装到单独的顶级可访问功能中(即稍后准备手动调用)。
  2. 将该功能作为我的馆藏success
  3. fetch()回调
  4. 这些集合的数量是未知的,我也无法找到所有这些集合的提取时间,并且我不想多次启动这些路由。所以我使用_.defer()_.once()
  5. 这很有效,但看起来很奇怪:

    路由器:

        window.startRoutes = _.once(function() {
    
            var AccountPage = Backbone.Router.extend({
    
              routes: {
                'set/:id': 'renderSet',
              },
    
              renderSet: function(setId) {
    
                  /** … **/
    
                  // Call the rendering method on the respective CardView
                  CardsViews[setId].render();
    
              }
    
            });
    
            var AccountPageRouter = new AccountPage;
    
            Backbone.history.start();
    
        });
    

    收集:

    window.CardsCollection = Backbone.Collection.extend({
    
        model: Card,
    
        initialize: function(params) {
    
            /** … **/
    
            // Get the initial data
            this.fetch({success: function() {
                _.defer(startRoutes);
            }});
    
        },
    
    });
    

    所以我的问题是......我做得对吗?或者有更好的方法(必须)吗?

2 个答案:

答案 0 :(得分:14)

您可以提前定义路由器;在你调用Backbone.History.start()之前,它不会做任何事情。

你可以绑定"重置"您的收藏中的活动可以像这样开始历史记录:

my_collection.bind("reset", _.once(Backbone.History.start, Backbone.History))

然后,当您的集合完全加载时,路由器将开始执行操作。我不确定这是否正是您正在寻找的(因为您提到了可变数量的集合)。

我有类似的情况,除了我事先知道在开始路由之前我想要加载哪些集合。我在我的路由器上添加了一个startAfter方法,如下所示:

  window.Workspace = new (Backbone.Router.extend({
    . . .
    startAfter: function(collections) {
      // Start history when required collections are loaded
      var start = _.after(collections.length, _.once(function(){
        Backbone.history.start()
      }))
      _.each(collections, function(collection) {
        collection.bind('reset', start, Backbone.history)
      });
    }
  }));

然后我设置了我的收藏品

  Workspace.startAfter([collection_a, collection_b, ...])

这也可以适用于独立模型,虽然我认为您需要绑定到“重置”之外的其他模式。事件

我很高兴我阅读了您的示例代码,使用_.once和_.defer指出了我正确的方向。

答案 1 :(得分:1)

我只是在使用它之前检查我的.render()方法是否填充了所有必填字段。如果它尚未填充 - 我正在呈现'正在加载... '小部件。

我的所有观看次数都按照this.model.bind('change', this.render, this);订阅了模型更改,因此在加载模型后,将再次调用render()