Backbone.js 如何使用AMD跟踪集合中的型号数量并与服务器保持同步
这里是Backbone.js新手。 一般问题:跟踪集合中的模型数量以便在UI上显示的最佳做法是什么?我的用例可能涉及服务器端的更改,因此每次同步集合时,我都需要能够从存储中将UI更新为正确的数字 我正在使用项目中的Backbone.jsv1.0.0和下划线v1.4.4以及Require.jsv2.1.6 特定示例:简单购物车,显示“购物车中的商品数量”,在用户添加/删除商品时不断更新。在这个例子中,我几乎做到了,但是(1)我的代码总是比实际模型数少一个,(2)我觉得有更好的方法来做到这一点 这是我的新手代码。 首先,我有一个项目集合,用户可以通过按钮将其添加到购物车中。(注意:为了简洁起见,代码示例中删除了所有AMD定义和返回。) 接下来,我有购物车中每个单独项目的视图PackageView,该视图由上面的PackagesView代码调用。我有一个“添加到购物车”按钮,每个包都有一个“点击”事件Backbone.js 如何使用AMD跟踪集合中的型号数量并与服务器保持同步,backbone.js,requirejs,backbone-views,amd,Backbone.js,Requirejs,Backbone Views,Amd,这里是Backbone.js新手。 一般问题:跟踪集合中的模型数量以便在UI上显示的最佳做法是什么?我的用例可能涉及服务器端的更改,因此每次同步集合时,我都需要能够从存储中将UI更新为正确的数字 我正在使用项目中的Backbone.jsv1.0.0和下划线v1.4.4以及Require.jsv2.1.6 特定示例:简单购物车,显示“购物车中的商品数量”,在用户添加/删除商品时不断更新。在这个例子中,我几乎做到了,但是(1)我的代码总是比实际模型数少一个,(2)我觉得有更好的方法来做到这一点 这是
var PackageView = Backbone.View.extend({
tagName:"div",
template:$(packageTemplate).html(),
events: {
"click .addToCart": "addToCart"
},
render:function () {
var tmpl = _.template(this.template);
this.$el.html(tmpl(this.model.toJSON()));
return this;
},
addToCart:function(){
cartView = new CartView();
cartView.collection.create(new CartItemModel(this.model));
}
最后,我有一个购物车视图,其中包含购物车中所有项目的集合。我尝试添加一个listenTo方法来响应集合的更改,但它也没有与服务器保持同步
var CartView = Backbone.View.extend({
el: $("#page"),
initialize:function(){
this.collection = new CartCollection();
this.collection.fetch({
reset: true
});
this.listenTo(this.collection, 'add', this.updateCartBanner);
this.collection.on("reset", this.render, this);
},
render: function(){
$('#cartCount').html(this.collection.length);
},
updateCartBanner: function(){
//things did not work here. Just putting this here to show something I tried.
}
特定示例的最终结果:创建工作正常,发送PUT请求,服务器将数据添加到数据库,调用“重置”事件。但是,CartView中的render()函数不显示集合中模型的右侧。第一次单击“添加到购物车”按钮时,$('#cartCount')元素未填充。然后在这之后的任何时候它都会被填充,但是我从服务器上的实际计数中减去1。我相信这是因为我有一个.create和一个.fetch,而.fetch发生在.create完成之前,所以我总是落后于服务器1
最终的结果是,我没有用正确的方式来构建这个。任何正确方向的提示都会很有帮助 您可以这样尝试:
collection.on("add remove reset sync", renderCallback)
renderCallback是一个刷新用户界面的函数。找到了我问题的答案,但肯定是一个更好的方法 如果我修改代码,而不是像上面那样为集合中的每个模型创建一个单独的视图,那么我有一个视图可以迭代所有模型并绘制,然后它就可以工作了。我仍然需要调用一个.create,后跟一个.fetch,并执行一些意外行为,但最终结果是正确的。 请注意,在这段代码中,我已经完全取消了以前的PackageView,现在所有内容都由PackageView绘制
var PackagesView = Backbone.View.extend({
el: $("#page"),
events: {
"click .addToCart": "addToCart"
},
initialize: function(id) {
this.collection = new PackagesCollection([],{id: id.id});
this.collection.fetch({
reset: true
});
this.collection.on("reset", this.render, this);
},
render: function(){
var that = this;
var tmpl = _.template($(packageTemplate).html());
//loop through models in collection and render each one
_.each(this.collection.models, function(item){
$(that.el).append(tmpl(item.toJSON()));
});
},
addToCart:function(e){
var id= $(e.currentTarget).data("id");
var item = this.collection.get(id);
var cartCollection = new CartCollection();
var cartItem = new CartItemModel();
cartCollection.create(new CartItemModel(item), {
wait: true,
success: function() {
console.log("in success create");
console.log(cartCollection.length);
},
error:function() {
console.log("in error create");
console.log(cartCollection.length);
}
});
cartCollection.fetch({
wait: true,
success: function() {
console.log("in success fetch");
console.log(cartCollection.length);
$('#cartCount').html(cartCollection.length);
},
error:function() {
console.log("in error fetch");
console.log(cartCollection.length);
}
});
结果:.fetch回调中的$(“#cartCount”)
注入了模型的正确数量。出乎意料的是,Chrome console.log返回的是正确的.html()值(服务器端从数据库中的零个模型开始):
我从create得到了200个响应,所以这两个回调都应该是“成功”的。我本以为create和fetch的主干回调语法是相同的。哦,好吧,它似乎起作用了
欢迎对该方法的任何反馈可能是更好的方法
顺便说一句,这违背了一般的建议,尽管我有一个“非常简单的列表”,所以从长远来看,这可能是可以的。您是否检查了从服务器返回的数据是否正确?(“Chrome调试器或Firebug中的“网络”选项卡,查找返回的XHR)我得到两个XHR响应,一个来自PUT请求(from.create),该请求返回200个状态,没有内容。另一个是来自GET请求(来自CartView的init中的.fetch)的响应,它确实没有正确的数字(-1)。但是我可以在服务器上看到PUT是成功的。我知道我不应该在initialize方法中使用.fetch,但我认为这不是真正的问题…只是我的调用和组织中的一些问题。尝试添加一个
this.listenTo(this.collection,'sync',this.updateCartBanner)
,如果这不起作用,也可以尝试在调用cartView.collection.CreateResult时添加一个wait:true
,作为选项的一部分。下面是我今天发现的一个可能的答案。
var PackagesView = Backbone.View.extend({
el: $("#page"),
events: {
"click .addToCart": "addToCart"
},
initialize: function(id) {
this.collection = new PackagesCollection([],{id: id.id});
this.collection.fetch({
reset: true
});
this.collection.on("reset", this.render, this);
},
render: function(){
var that = this;
var tmpl = _.template($(packageTemplate).html());
//loop through models in collection and render each one
_.each(this.collection.models, function(item){
$(that.el).append(tmpl(item.toJSON()));
});
},
addToCart:function(e){
var id= $(e.currentTarget).data("id");
var item = this.collection.get(id);
var cartCollection = new CartCollection();
var cartItem = new CartItemModel();
cartCollection.create(new CartItemModel(item), {
wait: true,
success: function() {
console.log("in success create");
console.log(cartCollection.length);
},
error:function() {
console.log("in error create");
console.log(cartCollection.length);
}
});
cartCollection.fetch({
wait: true,
success: function() {
console.log("in success fetch");
console.log(cartCollection.length);
$('#cartCount').html(cartCollection.length);
},
error:function() {
console.log("in error fetch");
console.log(cartCollection.length);
}
});
in error create PackagesView.js:88
0 PackagesView.js:89
in success fetch PackagesView.js:97
1