使用这个人为的示例代码:
var Product = Backbone.Model.extend({
idAttribute: '_id',
url: '/rest/product',
});
var Cart = Backbone.Collection.extend({
model: Product,
url: '/rest/cart',
});
p1 = new Product({name: 'Keyboard'});
p2 = new Product({name: 'Mouse'});
c = new Cart();
c.add([p1, p2]);
c.sync();
我看到Error: A "url" property or function must be specified
有很多帖子围绕着同样的错误消息,但我找到的所有帖子都是,恰当地,没有在路上某处定义的url属性或函数的结果。
我觉得好像错过了某个链接步骤 - 也许我隐含地依赖于Backbone.js实际上并没有自动设置的“魔术”连接/回调/属性/属性?
答案 0 :(得分:7)
我认为你不应该直接致电sync
;我认为您要找的是c.fetch()
(或p1.save(); p2.sav2()
,具体取决于您尝试发送数据的方向。同步正是Backbone在内部使用fetch
/ save
所做的事情(如果您想更改如何它们的AJAX详细信息,那么您需要进行同步覆盖,但否则你不应该需要它。)
如果您想方便地保存集合中的每个模型,您可以使用Underscore内置到集合方法“调用”(您应该可以c.save()
执行此操作,但我想您可以“T):
c.invoke('save');
答案 1 :(得分:3)
我首先退后一步,检查您的用例和您选择的架构。您显然正在尝试将产品添加到用户的购物车中。
我看到的问题是你已经把购物车变成了一个集合。我建议把购物车当作包含一系列产品的模型。
var ProductCollection = Backbone.Collection.extend({
model : Product
});
var Cart = Backbone.Model.extend({
url : '/rest/cart',
defaults : {
products : new ProductCollection()
}
});
使用这个新架构,你可以这样做:
var c = new Cart();
c.get('products').add([p1, p2]);
c.save();
此架构的另一个好处是,您可以在购物车中添加其他数据属性,例如客户ID,购物车创建时等等。
答案 2 :(得分:1)
对于sync()
,Backbone.sync
方法仅为a proxy。
fetch()
和save()
是sync()
的便捷方法,可让您假设第一个sync()
参数('read','patch','update',是一个给定的。
要自己调用此方法,您需要匹配此方法的方法签名才能直接调用它:
Backbone.sync = function(method, model, options)
以下是fetch()
的处理方式(注意传递的'read'参数,以及对模型的this
引用:
this.sync('read', this, options);
以下是save()
的作用:
method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
if (method === 'patch') options.attrs = attrs;
xhr = this.sync(method, this, options);
答案 3 :(得分:0)
在这种情况下使用save()
而不是sync()
save()
基本上通过代理执行Backbone.sync()
的工作,但应自动从save
的调用者处获取属性。
即使作为模型/集合中的方法调用sync()
,您也需要提供您希望同步的模型()作为第二个参数。
所以,myModel.sync('PUT',myModel)
会奏效。在具体情况下,c.sync('PUT',c)
答案 4 :(得分:0)
你无法以这种方式保存收藏品;它不是RESTful,因为REST完全是关于转移(单个)模型的状态。因此,Backbone.Collection不支持save()
。
一种解决方案是在集合上调用.invoke('save')
,正如@machineghost建议的那样,但注意这将导致对集合中每个模型的离散请求!如果您要保存多个模型,这可能不是一个好主意。
但是你可以随时保存一个Backbone.Model ......那么为什么不制作一个呢?
var Wrapper = Backbone.Model.extend({
url: 'api/endpoint'
});
var wrapper = new CollectionWrapperModel({
cart: c.models
});
wrapper.save();
或者,更简洁:
var wrapper = new (Backbone.Model.extend({url: 'api/endpoint'}))({cart: c});
wrapper.save();
请注意,服务器将收到一条POST或PUT消息,其中包含一个名为cart
的属性,这是一个包含多个模型的数组,需要进行适当的处理。
我意识到提问者为他的问题找到了不同的解决方案,但希望这会对某人有所帮助。