8

使用这个人为的示例代码:

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 实际上并没有自动设置的“神奇”连接/回调/属性/属性?

4

5 回答 5

7

我认为你不应该直接打电话sync;我认为您正在寻找的是c.fetch()(或者p1.save(); p2.sav2(),取决于您尝试发送数据的方向)。Sync 正是 Backbone 在内部使用来执行其fetch/的save(如果您想更改其执行方式的 AJAX 详细信息,则存在 sync 供您覆盖,否则不需要它)。

如果您想方便地将每个模型保存在集合中,您可以使用 Underscore 内置的集合方法“invoke”(您应该可以这样做c.save(),但我想您不能这样做):

 c.invoke('save');
于 2013-01-24T01:12:10.943 回答
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、购物车的创建时间等。

于 2013-01-24T06:44:28.103 回答
1

该方法sync()只是. _Backbone.sync

fetch()并且save()是 的一种便捷方法sync(),允许您假设第一个sync()参数(“read”、“patch”、“update”等)是给定的。

要自己调用它,您需要匹配此方法的方法签名才能直接调用它:

Backbone.sync = function(method, model, options)

这是它是如何fetch()做到的(注意传递的“读取”参数,以及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);
于 2013-01-24T04:25:52.683 回答
0

在这种情况下使用save(),而不是sync()

save()本质上是Backbone.sync()通过代理完成的工作,但应该自动从save.

当甚至从模型/集合作为方法调用时sync(),您需要提供您希望 sync() 作为第二个参数的模型。

所以,myModel.sync('PUT',myModel)会工作。在你的情况下,c.sync('PUT',c)

于 2015-06-11T22:27:32.617 回答
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,一个由多个模型组成的数组,需要对其进行适当处理。

我意识到提问者为他的问题找到了不同的解决方案,但希望这会对某人有所帮助。

于 2015-07-03T01:22:00.247 回答