【问题标题】:How to filter a Backbone collection on the server如何过滤服务器上的 Backbone 集合
【发布时间】:2014-09-10 12:20:09
【问题描述】:

Backbone 与过滤服务器上的集合的服务一起使用是否有一种通用模式?我无法在 Google 和 Stack Overflow 搜索中找到任何内容,这令人惊讶,考虑到生产中的 Backbone 应用程序的数量。


假设我正在使用 Backbone 为 Stack Overflow 构建一个新的前端。

在搜索屏幕上,我需要将以下信息传递给服务器并返回一页的结果。

  • 过滤条件
  • 排序标准
  • 每页结果
  • 页码

Backbone 似乎对将过滤卸载到服务器没有太大兴趣。它期望服务器返回整个问题列表并在客户端执行过滤。

我猜为了完成这项工作,我需要继承 Collection 并覆盖 fetch 方法,这样它就不会总是从同一个 RESTful URL 获取数据,而是传递上述参数。

我不想重新发明轮子。我是否缺少 Backbone 中的一项功能,该功能会使此过程更简单或更与现有组件兼容?是否已经有一个完善的模式来解决这个问题?

【问题讨论】:

    标签: web-services backbone.js collections filtering


    【解决方案1】:

    如果您只想在请求中传递 GET 参数,您应该能够在 fetch 调用本身中指定它们。

    collection.fetch( {
      data: {
        sortDir: "ASC",
        totalResults: 100
      }
    } );
    

    传递给 fetch 的选项应该直接转换为jQuery.ajax 调用,并且应该自动解析数据属性。当然,覆盖 fetch 方法也很好,特别是如果您想标准化部分逻辑。

    【讨论】:

    • 有没有办法像这样传递数据,而无需在 fetch 调用中执行?我记得之前在集合本身中定义了这样的过滤器字段,但不记得我是如何做到的。谢谢!
    【解决方案2】:

    你是对的,创建自己的Collection 是可行的方法,因为除了 OData 之外没有关于服务器分页的标准。

    在这些情况下,我通常会创建一个 collection.url 属性作为函数,而不是覆盖“fetch”,而是根据集合状态返回正确的 URL。

    但是,为了进行分页,服务器必须向您返回项目总数,以便您可以根据每页 X 个项目计算多少页。现在一些 API 使用 HAL 或 HATEOAS 之类的东西,它们基本上是 HTTP 响应标头。为了获得这些信息,我通常会在sync 事件中添加一个侦听器,该事件会在任何 AJAX 操作之后引发。如果您需要通知外部组件(通常是视图)可用项目/页面的数量,请使用事件。

    简单示例:您的服务器在响应标头中返回X-ItemTotalCount,并在请求查询字符串中期望参数pageitems

    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)

    您甚至可以将fetchNextfetchPrevious 方法添加到集合中,您只需修改this.currentPagefetch。如果您想用另一页替换一页而不是追加,请记住将{reset:true} 添加为fetch 选项。

    现在,如果您的项目后端是一致的,那么在使用相同的参数/响应的情况下,任何允许在服务器上进行分页的资源都可以在客户端上使用一个基于 PagedCollection 的集合来表示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多