骨干路由器:首先等待数据被获取
我想我不太明白骨干路由器的正确使用背后的想法。这就是我所得到的:
我有一些数据,当页面加载时,我从服务器获取这些数据,然后将其打包到模型和集合中。这些模型和系列的数量是无限的。我想使用路由器能够直接从一开始渲染特定集合的视图。
问题是:主干路由器启动较早,并且由于我要求它访问某个视图并触发其渲染操作,因此它无法执行此操作,因为这些视图尚未创建。这意味着我实际上必须在获取完成后启动我的路线。
我不知道这是否是正确的方法,但我想到的唯一想法是:
- 将路由定义和
Backbone.history.start();
位包装到单独的顶级可访问函数(即准备稍后手动调用它)。 - 运行该函数作为我的集合的
fetch()
的success
回调 - 这些集合的数量未知,而且我也无法知道何时全部获取,并且我不想多次启动路线。所以我使用
_.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:
- 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). - Run that function as the
success
callback for my collections’sfetch()
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以提前定义您的路由器;在您调用 Backbone.History.start() 之前它不会执行任何操作。
您可以在集合上绑定“重置”事件来启动历史记录,如下所示:
然后,当您的集合完全加载时,路由器将开始执行操作。我不确定这是否正是您正在寻找的(因为您提到拥有可变数量的集合)。
我也有类似的情况,只不过我在开始路由之前提前知道要加载哪些集合。我向我的路由器添加了一个 startAfter 方法,如下所示:
然后在我设置了我的集合之后,
这也可以适用于独立模型,尽管我认为您需要绑定到“重置”事件以外的其他内容。
我很高兴阅读您的示例代码,使用 _.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:
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:
and then after I've setup my collections
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.
我只是在使用之前检查我的
.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.