BackboneJs Collections 和 Rest API 调用
BackboneJs Collections and Rest API calls
我目前正在 backbone 中写博客 - 在此之前,我创建的任何 backbone 应用程序都相当小,所以我应该在初始化时获取我所有的 collection在应用程序上,将其存储在 collections 中并将它们传递给 collections 以供使用。
我面临着处理大量数据(博客文章)的问题。我不认为在一次调用中加载所有数据是最好的主意。我想做的是创建分页,它最初会请求说 9 条记录,计数为 post 和计数的当前页,然后对于每一页,我们对下一组数据等发出新请求。
请记住,我也在构建 Rest API,因此我对响应的格式没有任何限制。
我非常想按照 backbone 中的 collection 概念进行此操作 - 这可能吗?
如果有人以前做过这个或者有任何想法可以帮助我,那么将不胜感激。
你可以这样做:
var BlogPostsCollection = Backbone.Collection.extend({
url: function() {
return 'posts?page='+this.page;
},
fetch: function(options) {
this.page = options && options.page || 0;
return Backbone.Collection.prototype.fetch.apply(this, arguments);
},
parse: function(resp, options) {
var models = resp;
return _.map(models, function(model) {
model.page = options.page;
return model;
});
}
});
var BlogPostsView = Backbone.View.extend({
syncedPages: [],
events: {
'click .page': 'onPageClick'
},
initialize: function() {
this.filteredCollection = new Backbone.Collection();
this.listenTo(this.collection, 'request', this.onCollectionRequest);
this.listenTo(this.collection, 'sync', this.onCollectionSync);
this.listenTo(this.filteredCollection, 'reset', this.onFilteredCollectionReset);
this.requestingPage = 0;
this.collection.fetch({
page: this.requestingPage
});
this.render();
},
onPageClick: function(e) {
e.preventDefault();
this.requestingPage = +e.target.dataset.page;
if (this.syncedPages.indexOf(this.requestingPage) < 0) {
this.collection.fetch({
page: this.requestingPage,
remove: false // Important - merge the response models
});
} else {
this.filterToPage(this.requestingPage);
}
},
onCollectionRequest: function() {
this.filteredCollection.reset();
this.render();
},
onCollectionSync: function(collection, response, options) {
if (options.page === this.requestingPage) {
this.filterToPage(this.requestingPage);
}
this.syncedPages.push(options.page);
},
onFilteredCollectionReset: function() {
this.render();
},
filterToPage: function(page) {
this.currentPage = page;
this.filteredCollection.reset(this.collection.where({ page: page }));
},
render: function() {
if (!this.filteredCollection.length) {
this.$el.html('<p>Loading...</p>')
} else {
this.$el.empty();
this.filteredCollection.each(function(postModel) {
this.$el.append('<p>'+postModel.get('title')+'</p>');
}, this);
}
this.$el.append('<a href="#page0" class="page" data-page="0">Page 0</a> | <a href="#page1" class="page" data-page="1">Page 1</a>');
}
});
var blogPostView = new BlogPostsView({
el: $('#app'),
collection: new BlogPostsCollection()
});
显然该视图用于演示目的 - 使用 html 字符串,一个接一个地附加博客文章是次优的,应该有一个 BlogPostView 和一个 BlogNavigationView 等。
注意我添加了一些奖励逻辑:
- 页面抓取后,不需要重新抓取(remove:false + syncedPages)
- 如果出现多个请求,则不会混淆要显示的请求(由于 requestingPage 变量)。如果您点击第 1 页,然后返回第 0 页,它会立即再次显示第 0 页,但它会在后台缓存第 1 页。
我目前正在 backbone 中写博客 - 在此之前,我创建的任何 backbone 应用程序都相当小,所以我应该在初始化时获取我所有的 collection在应用程序上,将其存储在 collections 中并将它们传递给 collections 以供使用。
我面临着处理大量数据(博客文章)的问题。我不认为在一次调用中加载所有数据是最好的主意。我想做的是创建分页,它最初会请求说 9 条记录,计数为 post 和计数的当前页,然后对于每一页,我们对下一组数据等发出新请求。
请记住,我也在构建 Rest API,因此我对响应的格式没有任何限制。
我非常想按照 backbone 中的 collection 概念进行此操作 - 这可能吗?
如果有人以前做过这个或者有任何想法可以帮助我,那么将不胜感激。
你可以这样做:
var BlogPostsCollection = Backbone.Collection.extend({
url: function() {
return 'posts?page='+this.page;
},
fetch: function(options) {
this.page = options && options.page || 0;
return Backbone.Collection.prototype.fetch.apply(this, arguments);
},
parse: function(resp, options) {
var models = resp;
return _.map(models, function(model) {
model.page = options.page;
return model;
});
}
});
var BlogPostsView = Backbone.View.extend({
syncedPages: [],
events: {
'click .page': 'onPageClick'
},
initialize: function() {
this.filteredCollection = new Backbone.Collection();
this.listenTo(this.collection, 'request', this.onCollectionRequest);
this.listenTo(this.collection, 'sync', this.onCollectionSync);
this.listenTo(this.filteredCollection, 'reset', this.onFilteredCollectionReset);
this.requestingPage = 0;
this.collection.fetch({
page: this.requestingPage
});
this.render();
},
onPageClick: function(e) {
e.preventDefault();
this.requestingPage = +e.target.dataset.page;
if (this.syncedPages.indexOf(this.requestingPage) < 0) {
this.collection.fetch({
page: this.requestingPage,
remove: false // Important - merge the response models
});
} else {
this.filterToPage(this.requestingPage);
}
},
onCollectionRequest: function() {
this.filteredCollection.reset();
this.render();
},
onCollectionSync: function(collection, response, options) {
if (options.page === this.requestingPage) {
this.filterToPage(this.requestingPage);
}
this.syncedPages.push(options.page);
},
onFilteredCollectionReset: function() {
this.render();
},
filterToPage: function(page) {
this.currentPage = page;
this.filteredCollection.reset(this.collection.where({ page: page }));
},
render: function() {
if (!this.filteredCollection.length) {
this.$el.html('<p>Loading...</p>')
} else {
this.$el.empty();
this.filteredCollection.each(function(postModel) {
this.$el.append('<p>'+postModel.get('title')+'</p>');
}, this);
}
this.$el.append('<a href="#page0" class="page" data-page="0">Page 0</a> | <a href="#page1" class="page" data-page="1">Page 1</a>');
}
});
var blogPostView = new BlogPostsView({
el: $('#app'),
collection: new BlogPostsCollection()
});
显然该视图用于演示目的 - 使用 html 字符串,一个接一个地附加博客文章是次优的,应该有一个 BlogPostView 和一个 BlogNavigationView 等。
注意我添加了一些奖励逻辑:
- 页面抓取后,不需要重新抓取(remove:false + syncedPages)
- 如果出现多个请求,则不会混淆要显示的请求(由于 requestingPage 变量)。如果您点击第 1 页,然后返回第 0 页,它会立即再次显示第 0 页,但它会在后台缓存第 1 页。