我通常是从事J2EE(servlet / ejb)框架和库的后端人员。全新的前端,尤其是Backbone。因此,问题有点像菜鸟。我会很感激任何意见/教程/例子。我将尽可能清楚,精细地解释我的目标/要求。
这是我的第一个SO问题,因此提前为违反任何规则道歉。
Q值。我有一个后端电子商务引擎,它将REST URL作为产品目录API的一部分公开。 API 1 - / rest / repository / atg / commerce / catalog / ProductCatalog / product /。 API 1将产品列表作为单个JSON数组进行响应。这里有趣的是,它只为每个产品发送单独的REST URL。样品响应:
{"product": [
"http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90004",
"http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90005",
"http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod100027"
"http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod70011",
"http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod70013"
]}
API 2 - http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/ productId 即。 http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product/prod90004 基本上是API 1响应中的单个产品URL之一 样品响应:
{
"dateAvailable": "2000-05-04 15:51:42.521",
"displayName": "Warm Black Gloves ",
"longDescription": "Protects you from the elements and keeps you looking good, these durable gloves won't let you down.",
"repositoryId": "prod90004"
}
必需目标:如果API 1使用包含4个URL(即4个产品)的JSON数组作出响应,那么我需要在视图中显示4个产品的属性,依此类推。可以通过对API 2进行4次调用来检索属性;换句话说,对API 1中收到的URL发出4个请求。
问题: 我已经研究了一些教程和示例。我无法以某种方式获得有关此特定用例的任何内容。我已经看到的示例假设将有一个REST API,它将使用包含所有模型(在这种情况下为产品)的JSON数组及其属性在单个JSON响应中进行响应。但是,这不是这种情况,因为我必须首先调用API 1来获取产品URL列表,然后调用所有这些URL(在API 1的响应中检索)以获取相应模型的属性。因此,我无法决定如何定义模型,集合和URL属性等。
我试过如下:
(function ($) {
var ProductView = Backbone.View.extend({
tagName:"div",
className:"bookContainer",
template:$("#bookTemplate").html(),
render:function () {
console.log("inside render of ProductView");
var tmpl = _.template(this.template);
this.$el.html(tmpl(this.model.toJSON()));
return this;
}
});
var ProductModel = Backbone.Model.extend({
defaults:{
displayName:"displayName",
longDescription:"longDescription",
dateAvailable:"dateAvailable",
repositoryId:"repositoryId",
},
initialize: function(){
this.on("reset", this.renderModelView, this);
this.fetch({
reset:true,
error:function () {
console.log(arguments);
}
});
},
renderModelView: function(){
var that = this;
new ProductView.render({
model: that
});
}
});
var ProductCollection = Backbone.Collection.extend({
model: ProductModel,
initialize: function(){
this.on("reset", this.debugTempfunc, this);
this.fetch({
reset:true,
error:function () {
console.log(arguments);
}
});
},
debugTempfunc: function(){
console.log("collection length: "+this.length);
}
});
var ProductURLModel = Backbone.Model.extend({
defaults:{
product: "ProductCatalogProductURLs"
}
});
var ProductURLCollection = Backbone.Collection.extend({
model: ProductURLModel,
url: "http://example.com/rest/repository/atg/commerce/catalog/ProductCatalog/product",
initialize: function(){
this.on("reset", this.populateModels, this);
this.fetch({
reset:true,
error:function () {
console.log(arguments);
}
});
},
populateModels: function(){
var ProductCollectionIns = new ProductCollection();
var that = this;
console.log("inside populateModels of ProductURLCollection: "+that);
_.each(that.models[0].attributes.product,function(item){
console.log("populateModels, item value: "+item);
ProductCollectionIns.url=item;
ProductCollectionIns.fetch();
});
}
});
var ProductURLCollectionTestIns = new ProductURLCollection();
})(jQuery);
我的计划是首先将ProductURLCollection定义为一个集合,其URL设置为API 1的URL。此集合将具有单个模型ProductURLModel,其将具有n个ProductURLModel(s)... n是在API 1中检索的URL的数量,其也等同于产品的数量。这表明现在我必须进行n次API 2调用。为此,我决定制作另一个包含n个ProductModel的集合ProductCollection。 ProductCollection的url属性将在迭代ProductURLCollection模型时动态设置,如下面的代码所示:
populateModels: function(){
var ProductCollectionIns = new ProductCollection();
var that = this;
console.log("inside populateModels of ProductURLCollection: "+that);
_.each(that.models[0].attributes.product,function(item){
console.log("populateModels, item value: "+item);
ProductCollectionIns.url=item;
ProductCollectionIns.fetch();
});
}
有了这个,我希望每次更改ProductCollectionIns url时都可以动态生成n个ProductModel。但是,我得到“错误:必须指定”url“属性或函数”。这是否意味着没有设置ProductCollectionIns url属性?
我相信必须有一种更简单的方法来实现Backbone中的上述功能。请赞赏任何解决方案或更好的实施方案。
答案 0 :(得分:2)
让我解释一下Backbone的AJAX系统是如何工作的,首先是Model
(但我会在一分钟内到达Collection
)。简而言之,Backbone旨在让您能够做到:
var FooModel = Backbone.Model.extend({url: 'www.example.com'});
var someModel = new FooModel({id: 5});
someModel.fetch().done(function() {
// Now someModel should be populated with the AJAX data for model #5
});
在幕后发生的事情当你致电fetch
时,Backbone会查找与Model
相关联的网址。由于您从未定义过一个(或urlRoot
),因此您会收到错误,因为Backbone不知道在哪里进行AJAX调用。
一旦您通过url
属性告知Backbone在哪里可以找到该类型模型的数据,Backbone将会调用www.example.com/5' (因为模型的id
为5)。然后Backbone将期望该URL返回类似于以下内容的响应:
{id: 1, someAttribute: 2, someOtherAttribute: 'spam'}
JSON将成为someModel
的属性,因此您可以做到:
someModel.get('someAttribute'); // == 2
Collection
的工作方式几乎相同,只是他们期望JSON响应为:
[{id: 1, someAttribute: 2, someOtherAttribute: 'spam'},
{id: 2, someAttribute: 55, someOtherAttribute: 'eggs'}]
并将返回数组的每个成员转换为Model
。
正如您所推测的,有一种比populateModels
方法更简单的方法:如果您只是遵循我描述的模式,您的收藏应该自动创建模型而不需要额外的努力。如果您确实需要自定义内容(例如,您想要将来自服务器的" foo"属性更改为" bar"属性),则可以覆盖{{1} }'或Model
' Collection
方法,它采用" raw" AJAX数据并返回转换后的版本:
parse
希望有所帮助。