這是我的破解快速運行你的代碼。我沒有測試過任何東西,所以可能會出現拼寫錯誤。我仍然不確定哪裏會出現流浪的空模型,但如果您按照以下所述重構應用程序,我懷疑問題會消失。
模型和集合看起來不錯,讓我們看看你的看法。
el: $('#todos'),
listBlock: $('#todos-list'),
newTodoField: $('#add input'),
//...
template: $('#todo-template').html(),
//...
events: { /* ... */ },
這些應該沒問題,但是您需要確保當您的視圖「class」加載時,所有這些元素都在DOM中。通常你會編譯模板一次:
template: _.template($('#todo-template').html()),
,然後只用this.template
作爲一個函數來獲取你的HTML。我將假設template
是下面編譯的模板函數。
initialize: function() {
_this = this;
您在這裏有一個意外的全局變量,這可能會導致有趣的錯誤。你想說var _this = this;
。
this.el = $(this.el);
骨幹已經給你el
在$el
的jQuery'd版本,所以你不需要這麼做,只是使用this.$el
。
this.collection.fetch({
success : function(collection, response) {
_.each(response, function(i) {
var todo = new TodosModel({ /* ... */ });
// Add to collection
_this.collection.add(todo);
// Render
_this.render(todo);
});
},
//...
收集的fetch
將success
處理程序之前的模型添加到集合稱爲所以你不必創建新模型或添加任何東西到集合中。一般來說,render
方法渲染整個事物,而不是隻渲染一個部分,並將視圖的render
綁定到集合的"reset"
事件;該fetch
通話將觸發"reset"
事件時,它已經提取所以通常的模式是這樣的:
initialize: function() {
// So we don't have to worry about the context. Do this before you
// use `render` or you'll have reference problems.
_.bindAll(this, 'render');
// Trigger a call to render when the collection has some stuff.
this.collection.on('reset', this.render);
// And go get the stuff we want. You can put your `error` callback in
// here if you want it, wanting it is a good idea.
this.collection.fetch();
}
現在對於render
:
render: function (todo) {
var templ = _.template(this.template);
this.listBlock.append(templ({
id: todo.get('id'),
content: todo.get('content'),
completed: todo.get('completed')
}));
// Mark completed
if(todo.get('completed')) {
this.listBlock.children('li[data-id="'+todo.get('id')+'"]')
.addClass('todo-completed');
}
}
通常這會被分成兩個部分:
render
呈現整個集合。
- 另一種方法,如
renderOne
,呈現單個模型。這也允許您將renderOne
綁定到該集合的"add"
事件。
因此,像這將是典型的:
render: function() {
// Clear it out so that we can start with a clean slate. This may or
// may not be what you want depending on the structure of your HTML.
// You might want `this.listBlock.empty()` instead.
this.$el.empty();
// Punt to `renderOne` for each item. You can use the second argument
// to get the right `this` or add `renderOne` to the `_.bindAll` list
// up in `initialize`.
this.collection.each(this.renderOne, this);
},
renderOne: function(todo) {
this.listBlock.append(
this.template({
todo: todo.toJSON()
})
)
// Mark completed
if(todo.get('completed')) {
this.listBlock.find('li[data-id="' + todo.id + '"]')
.addClass('todo-completed');
}
}
注意使用toJSON
提供數據的模板。骨幹模型和集合有一個toJSON
方法來給你一個簡化版本的數據,所以你不妨使用它。該模型的id
可作爲屬性使用,因此您不必使用get
即可獲取。你可以(並且可能應該)推todo-completed
邏輯到模板,只是有點
<% if(completed) { %>class="completed"<% } %>
在正確的地方應該做的伎倆。
addTodo: function (e) {
//...
var todo = new TodosModel({
id: todoID,
content: todoContent,
completed: todoCompleted
});
this.render(todo);
todo.save();
_this.collection.add(todo);
你可以綁定renderOne
到集合的"add"
事件採取渲染新模式的照顧。然後使用save
回調來完成它:
var _this = this;
var todo = new TodosModel({ /* ... */ });
todo.save({}, {
wait: true,
success: function(model, response) {
// Let the events deal with rendering...
_this.collection.add(model);
}
});
同樣,一個error
回調的save
可能是好的。
completeTodo: function (e) {
//...
todo.save({
completed: todoCompleted
});
}
的save
來電來訪將掀起'change:completed'
事件,這樣你可以綁定到調整HTML。
removeTodo: function (e) {
//...
}
的destroy
通話將觸發模型and on the collection一個"destroy"
事件:
被觸發集合模型中的任何事件也會 可以在收集直接觸發,以方便使用。這 可以讓你聽一個集合中的變化,以特定的屬性在任何模型 ,[...]
所以,你可以聽上收集"destroy"
事件,並使用這些從顯示屏中刪除TODO 。如果沒有您的介入,銷燬模型應該將其從集合中刪除。
printColl: function() {
this.collection.each(function (todo) {
console.log('ID: '+todo.get('id')+' | CONTENT: '+todo.get('content')+' | COMPLETED: '+todo.get('completed'));
});
}
你可以只console.log(this.collection.toJSON())
相反, 你必須按一下週圍一點點開拓在 控制檯的東西,但你不會錯過任何東西的方式。
集合的所有事件綁定都將發生在您的 視圖的initialize
方法中。如果你要刪除的視圖,然後 你想覆蓋remove
從收集 解除綁定,以防止內存泄漏:
remove: function() {
// Call this.collection.off(...) to undo all the bindings from
// `initialize`.
//...
// Then do what the default `remove` does.
this.$el.remove()
}
你也可以使用一個單獨查看每個TODO項目但可能會讓事情變得簡單。
如果你有'_(response).each(function(o){console.log(o)});'?你的'每個人'可能會挑選你不期望的'迴應'。 –
我很想知道,但這是我得到的:http://i.imgur.com/rxqcS.png – Fluidbyte
以下是完整的代碼:http://sandbox.fluidbyte.org/todos/js/todos。 js – Fluidbyte