更新服务器上的所有模型后,我在刷新集合或更准确地说 Collection View 时遇到问题。这是我的场景:
我从服务器获取了一系列问题。每个问题都有一个位置属性,因此我可以操纵列表中的顺序并以适当的顺序将其保存回服务器。
我有每个列表项的 View 和具有更全局范围的 View ,该 View 生成每个列表项并更新集合。基本上,我使用的是 O'Reilly 书籍“Javascript Web 应用程序”中的示例,它与此处找到的著名的 Todo 带注释教程非常相似: http://documentcloud.github.com/backbone/docs/todos.html 因此,除了一些定制模型之外,结构几乎相同。一切正常。
但是,我在更新集合时遇到问题,因为我重新排序了 我的全局 View 中有一个方法,每当我在列表中拖动列表项时都会触发该方法。顺便说一句,它运行良好并更新服务器上项目的顺序,但我也希望能够更新列表中每个项目的数字。
window.QuestionView = Backbone.View.extend({ el: $("#content"), events : { 'sortupdate ol#questions': 'sortStuff' }, initialize: function(collection) { this.collection = new QuestionsList; _.bindAll(this, 'addOne', 'addAll', 'render', 'addNewItem', 'addItem'); this.collection.bind('add', this.addNewItem); this.collection.bind('all', this.render); this.collection.bind('reset', this.addAll); this.collection.fetch({ data: { quiz_id: $qid }, processData:true }); }, render: function() {}, sortStuff: function() { $this = this; $.ajax({ url: "/hq/reorder/", type: "POST", data: $("#questions").sortable("serialize")+"&id="+$qid, dataType: 'json', success: function(data) { } }); }, addItem: function() { this.collection.add({title: 'New title goes here'}); return false; }, addNewItem: function(question) { var view = new ItemView({model: question, parent: this}); var element = view.render().el; this.$("#questions").prepend(element); $that = this; $(view.render().el).addClass('new'); }, addOne: function(question) { var view = new ItemView({model: question, parent: this}); this.$("#questions").prepend(view.render().el); }, addAll: function() { this.collection.each(this.addOne); return false; }
});
还有我的 成功:函数(数据) 从服务器返回新订单作为列表(或 JSON 对象)。也许我可以重用此订单来为每个模型设置新值,而无需每次更改订单时在服务器上进行不必要的 fetch() 调用?
编辑:
我终于设法让它通过重置、清除 View 并重新获取新集合来工作。也许这不是最好的方法,因为需要使用 fetch() 对服务器进行额外的调用..
sortStuff: function() {
$this = this;
$.ajax({
url: "/hq/reorder/",
type: "POST",
data: $("#questions").sortable("serialize")+"&id="+$qid,
dataType: 'json',
success: function(data) {
$this.rerender();
}
});
},
rerender: function() {
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
$("#questions").html("");
this.collection.reset();
this.addAll();
},
最佳答案
我认为你的方法应该分为两个单独的步骤: 1)一方面你更新服务器上的数据 2) 另一方面,您更新集合客户端
所以,您在第 1 步上没问题,您说它有效。
对于步骤 2,您可以利用事件驱动编程。 逻辑是这样的:
- 您只需向集合中添加一个元素(collection.add(model) 会触发“add”事件)。
- 在集合中,您监听“add”事件。当您捕获它时,您将再次对集合进行排序(collection.sort 会触发“重置”事件)
- 在 ListView 中(在您的例子中为 QuestionView),您监听集合重置事件,一旦触发,您将重新渲染 View
示例代码:
1) QuestionView:删除了 addItem 并简化了 addNewItem(不得渲染)
window.QuestionView = Backbone.View.extend({
el: $("#content"),
events : {
'sortupdate ol#questions': 'sortStuff'
},
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
},
render: function() {},
sortStuff: function() {
$this = this;
$.ajax({
url: "/hq/reorder/",
type: "POST",
data: $("#questions").sortable("serialize")+"&id="+$qid,
dataType: 'json',
success: function(data) {
}
});
},
//METHOD addItem REMOVED!!!
addNewItem: function(question) {
this.collection.add({title: 'New title goes here'}); //***IT FIRES AN ADD EVENT
},
addOne: function(question) {
var view = new ItemView({model: question, parent: this});
this.$("#questions").prepend(view.render().el);
},
addAll: function() {
this.collection.each(this.addOne);
return false;
}
});
2)集合捕获添加事件并排序(触发“重置”事件) 您可以始终在 QuestionView 中处理它,您的初始化函数将变为。
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
//ADD THIS*****
this.collection.on('add', function(){
this.collection.sort();
});
},
3)第三步已经完成,你只需重新渲染 View
最好的方法是对集合中的元素进行排序,定义一个新的“比较器”函数,该函数使用列表的“位置”属性
类似于(在 QuestionView 中)
this.collection.comparator: function(){
return this.collection.get("position");
}
以便项目按位置排序客户端
**编辑** 修改初始化函数。使用fetch代替'sort',只要集合中每个元素的'position'属性不更新,这是没有用的。
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
//ADD THIS*****
this.collection.on('add', function(){
this.collection.fetch();
});
关于javascript - Backbone 收藏刷新所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9309893/