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

发布于 2024-12-10 12:28:57 字数 1402 浏览 0 评论 0原文

我想我不太明白骨干路由器的正确使用背后的想法。这就是我所得到的:

我有一些数据,当页面加载时,我从服务器获取这些数据,然后将其打包到模型和集合中。这些模型和系列的数量是无限的。我想使用路由器能够直接从一开始渲染特定集合的视图。

问题是:主干路由器启动较早,并且由于我要求它访问某个视图并触发其渲染操作,因此它无法执行此操作,因为这些视图尚未创建。这意味着我实际上必须在获取完成后启动我的路线。

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

  1. 将路由定义和 Backbone.history.start(); 位包装到单独的顶级可访问函数(即准备稍后手动调用它)。
  2. 运行该函数作为我的集合的 fetch()success 回调
  3. 这些集合的数量未知,而且我也无法知道何时全部获取,并且我不想多次启动路线。所以我使用 _.defer()_.once()

这可行,但看起来确实很奇怪:

Routers:

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

    });

Collection:

window.CardsCollection = Backbone.Collection.extend({

    model: Card,

    initialize: function(params) {

        /** … **/

        // Get the initial data
        this.fetch({success: function() {
            _.defer(startRoutes);
        }});

    },

});

所以我的问题是……我做得对吗?或者有更好的方法来做到这一点(必须是)?

I think I don’t quite get the idea behind the proper usage of Backbone routers. Here’s what I’ve got:

I have some data that I fetch from the server when the page loads and then pack it into models and collections. The number of those models and collections is indefinite. I want to use the router to be able to render the certain collection’s view directly from the start.

The problem is: Backbone router starts up early, and since I ask it to access a certain view and trigger its render action, it cannot do that, because those views are not yet created. That means I actually have to make my routes start up after the fetch is complete.

I don’t know if this is a proper way to do it, but the only idea I came up with is to:

  1. Wrap the routes definition and the Backbone.history.start(); bit into a separate top-level-accesible function (i.e. prepare to call it manually later on).
  2. Run that function as the success callback for my collections’s fetch()
  3. The number of those collections is unknown, also I have no way to find out when all of them have been fetched, and I don’t want to start the routes more than once. So I make use of _.defer() and _.once().

This works, but it sure looks very weird:

Routers:

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

    });

Collection:

window.CardsCollection = Backbone.Collection.extend({

    model: Card,

    initialize: function(params) {

        /** … **/

        // Get the initial data
        this.fetch({success: function() {
            _.defer(startRoutes);
        }});

    },

});

So my question is… am I doing it right? Or is there a better way to do this (must be)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷途知返 2024-12-17 12:28:57

您可以提前定义您的路由器;在您调用 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 为我指明了正确的方向。

You can define your router ahead of time; it won't do anything until you call Backbone.History.start().

You can bind the "reset" event on your collection to start history like this:

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

Then the router will start doing stuff when your collection is fully loaded. I'm not sure if this is exactly what you're looking for (since you mentioned having a variable number of collections).

I have a similar situation, except that I know in advance which collections I want to have loaded before I start routing. I added a startAfter method to my Router, like so:

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

and then after I've setup my collections

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

This could be adapted to work with standalone models too, although I think you'd need to bind to something other than the 'reset' event.

I'm glad I read your example code, the use of _.once and _.defer pointed me in the right direction.

征﹌骨岁月お 2024-12-17 12:28:57

我只是在使用之前检查我的 .render() 方法是否已填写所有必填字段。如果尚未填充 - 我正在渲染一个“正在加载...”小部件。

我的所有视图都通过 this.model.bind('change', this.render, this); 订阅模型更改,因此在加载模型后,render() 将再次被调用。

I'm just checking in my .render() method that all required fields are filled, before using it. If it's not filled yet - i'm rendering an 'Loading...' widget.

And all my views are subscribed to model changes, by this.model.bind('change', this.render, this);, so just after model will be loaded, render() will be called again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文