【发布时间】:2012-08-21 01:53:00
【问题描述】:
简短版:我有一个 Backbone 模型,它的属性之一是第二个 Backbone 模型。第一个模型中的一个函数改变了第二个模型的状态,但是我的视图,它正在监听第一个模型的变化,似乎没有拾取第二个模型的状态,尽管有任何数量的日志记录表明不是这样(我一直在各个点记录this 以确认范围等)。我该如何解决这个问题?
长版:我有一个Backbone 模型Course,它代表一门学术课程,还有一个模型NameList,它代表一个Course 注册的学生列表。 Course“有”NameList。 NameList 由服务器上的单个文本文件支持。
我想在 Course 模型中创建一个名为 importNameList 的函数,该函数创建一个新的 NameList 模型,并导致 NameList 模型和 fetch 来自后端的数据。由于我的观点,CourseView 正在监听Course 模型的更改,而Course 模型具有-a NameList,看来这应该相应地更新视图。我的问题是它没有。
我想做的事
var course = new Course();
var courseView = new CourseView({model : course});
courseView.model.importNameList('students.txt'); // Will cause view to re-render
我必须做什么
var course = new Course(); // same
var courseView = new CourseView({model : course}); // same
courseView.model.importNameList('students.txt'); // same
courseView.render(); // Argh, manually calling this is ugly.
这是我的带有日志记录语句的代码。模型扩展 Backbone.DeepModel 只是因为我认为它可以解决我的问题,但它没有。
控制台输出
[console] var course = new Course();
[console] var courseView = new CourseView({model : course});
[console] course.importNameList('students.txt');
Course >>> importNameList
NameList >>> initialize()
NameList >>> fetch()
GET http://localhost/files/students.txt 200 OK 16ms
CourseView >>> render() // Render starts before fetch completes
CourseView <<< render() // Render finishes before fetch completes
Course <<< importNameList
NameList <<< fetch()
[console] courseView.render();
CourseView >>> render()
alice
bob
charlie
dan
erica
fred
george
CourseView <<< render()
Course.js
var Course = Backbone.DeepModel.extend({
defaults : {
nameList : new NameList()
},
initialize: function(options) {
if (options && options.nameList) {
this.set({nameList : options.nameList});
}
},
importNameList : function(fileName) {
console.log("Course >>> importNameList");
var nameList = new NameList({fileName : fileName});
this.set({nameList : nameList});
console.log("Course <<< importNameList");
}
});
NameList.js
var NameList = Backbone.DeepModel.extend({
defaults : {
fileName : 'new.txt',
names : []
},
initialize: function(options) {
console.log("NameList >>> initialize()");
var model = this;
if (options && options.fileName) {
model.set({fileName : options.fileName});
}
model.fetch();
},
fetch : function() {
console.log("NameList >>> fetch()");
var model = this;
$.ajax({
url : '/files/' + model.get('fileName'),
success : function(response) {
model.set({names : response.split('\n')});
console.log("NameList <<< fetch()");
}
});
}
});
CourseView.js
var CourseView = Backbone.View.extend({
initialize : function(options) {
var view = this;
if (options && options.model) {
view.model = options.model;
} else {
view.model = new Course();
}
view.model.on('change', function() {
view.render();
});
},
render : function() {
console.log("CourseView >>> render()");
var names = this.model.get('nameList').get('names');
for (var i = 0; i < names.length; i++) {
console.log(names[i]);
}
console.log("CourseView <<< render()");
return this;
}
});
【问题讨论】:
-
为什么要在 NameList.js 中覆盖
fetch?这似乎与backbone.js 的用途完全相反。您不应该直接调用 ajax 函数来更新模型。