你是对的,创建自己的Collection 是可行的方法,因为除了 OData 之外没有关于服务器分页的标准。
在这些情况下,我通常会创建一个 collection.url 属性作为函数,而不是覆盖“fetch”,而是根据集合状态返回正确的 URL。
但是,为了进行分页,服务器必须向您返回项目总数,以便您可以根据每页 X 个项目计算多少页。现在一些 API 使用 HAL 或 HATEOAS 之类的东西,它们基本上是 HTTP 响应标头。为了获得这些信息,我通常会在sync 事件中添加一个侦听器,该事件会在任何 AJAX 操作之后引发。如果您需要通知外部组件(通常是视图)可用项目/页面的数量,请使用事件。
简单示例:您的服务器在响应标头中返回X-ItemTotalCount,并在请求查询字符串中期望参数page 和items。
var PagedCollection = Backbone.Collection.extend({
initialize: function(models,options){
this.listenTo(this, "sync", this._parseHeaders);
this.currentPage = 0;
this.pageSize = 10;
this.itemCount = 0;
},
url: function() {
return this.baseUrl + "?page=" + this.currentPage + "&items=" + this.pageSize;
},
_parseHeaders: function(collection,response){
var totalItems = response.xhr.getResponseHeader("X-ItemTotalCount");
if(totalItems){
this.itemCount = parseInt(totalItems);
//trigger an event with arguments (collection, totalItems)
this.trigger("pages:itemcount", this, this.itemCount);
}
}
});
var PostCollection = PagedCollection.extend({
baseUrl: "/posts"
});
请注意,我们使用另一个自己的属性 baseUrl 来简化 PagedCollection 的扩展。如果你需要添加自己的initialize,就这样调用父级的原型,否则你不会解析标题:
PagedCollection.protoype.initialize.apply(this,arguments)
您甚至可以将fetchNext 和fetchPrevious 方法添加到集合中,您只需修改this.currentPage 和fetch。如果您想用另一页替换一页而不是追加,请记住将{reset:true} 添加为fetch 选项。
现在,如果您的项目后端是一致的,那么在使用相同的参数/响应的情况下,任何允许在服务器上进行分页的资源都可以在客户端上使用一个基于 PagedCollection 的集合来表示。