将参数传递给backbone fetch url以处理非标准api

时间:2014-10-28 23:33:13

标签: javascript jquery ajax backbone.js backbone.js-collections

我试图操纵骨干的fetch方法来处理一些非标准的api。 api的工作方式如下:

api/products/[page]?param1=val&param2=val

例如:

api/products/2?budget=low&categories=all

等同于获得预算较低且包含所有类别的第二页结果。

我可以通过以下格式在查询字符串之后传递参数:

self.productsItemsCollection.fetch({ success : onDataHandler, dataType: "json", data: { budget: 'low', categories: 'all' } });

但我不知道如何处理分页,因为它出现在?之前?问号。

以下是如何设置集合:

define([
  'underscore',
  'backbone',
  'models/products/ProductsItemsModel'
], function(_, Backbone, ProductsItemsModel){

  var ProductsItemsCollection = Backbone.Collection.extend({

      model: ProductsItemsModel,

      initialize : function(models, options) {}, //MH - need to pass filters to this function

      url : function() {
        return '/api/products/'; //MH - need to pass page number to be appended to this url
      },

      parse : function(data) {
        debugger;
        return data.items;
      }

  });

  return ProductsItemsCollection;

});

如果给定此api URL结构,如何在backbone的fetch命令中包含分页?

3 个答案:

答案 0 :(得分:3)

您正走在正确的轨道上,因为Backbone可以使用函数的返回值作为其' url'值。我个人会做的是在集合上设置一个页面属性(通过类似this.page引用),并将其包含在url函数的输出中。

initialize: function() {
  this.page = 1; // Or whatever the default should be
},
url: function() {
  return '/api/products/ + this.page;
}

然后问题就出现了更新页面属性,这可以像&Products;商品指南-Collection.page = 2;'一样简单。就个人而言,我还会添加第二个fetch方法来包装页面更新并将其提取到单个方法调用中。

fetch2: function(page, options) {
  if (page) {
    this.page = page;
  }
  return this.fetch(options);
}

答案 1 :(得分:0)

您的代码只需几个注释。我认为您不需要在收藏夹中定义页码。根据MVC模式,它更适合Controller。集合只需获取参数并根据它返回一些数据。同时Backbone不提供经典的MVC控制器,但您可以将Backbone.View用于此目的。因此,您的应用程序的结构可能如下所示:

    // Collection
    define([
      'backbone',
      'models/products/ProductsItemsModel'
    ], function(Backbone, ProductsItemsModel){

      return Backbone.Collection.extend({

      // I don't know what exactly your Model does, but if you don't override Backbone.Model with your own methods you don't really need to define it into your collection.
      model: ProductsItemsModel,

      initialize : function(models, options) {}, //MH - need to pass filters to this function

      url : function(page) {
        return '/api/products/' + page;
      },

      parse : function(data) {
        return data.items;
      }
  });
});

然后在您的视图中,您可以获取所需的页面并进行渲染:

define([
  'jquery',
  'backbone',
  'ProductsItemsCollection'
], function($, Backbone, ProductsItemsCollection){

  return Backbone.View.extend({

      events: {

          // Your logic to get page number from your pagination.
          'click .pagination': 'getPageNumber'
      }

      collection: new ProductsItemsCollection(),

      initialize : function() {
          this.listenTo(this.collection, 'reset', this.render);

          // initial loading collection
          this.load(1); // load page #1
      },

      render: function () {
          // your render code
      }

      // Example function to show how you could get page number.
      getPageNumber: function(e) {
          var pageNumber = $(e.currentTarget).data('pageNumber');
          load(pageNumber);
      },

      load: function(page) {
          url: this.collection.url(page),
          data: {
              budget: 'low',
              categories: 'all'
          }
      }
  });
});

这样的事情。因此,在此视图中,您只需初始化Collection并进行初始加载。然后你应该做的就是将页码传递给你的加载函数。

答案 2 :(得分:0)

我读了这些答案,我猜他们有意义,但这就是我的意思。真的很简单:

app.WorkOrder = Backbone.Collection.extend({
    model: app.WorkOrderDetail,
    urlRoot: '/m2/api/w/',
    getWorkOrder: function(workorder_id, options) {
        this.url = this.urlRoot + workorder_id;
        return this.fetch(options);
    }
});

然后在视图中我这样做:

    app.AppView = Backbone.View.extend({
    el: '#workorderapp',
    initialize: function () {
        app.workOrder.getWorkOrder(workorder_id, {
            success:function(data) {
                //...do something with data
            }
        });
    },
});