题
我正在尝试在我的第一个“真实”应用程序中使用backbone.js,我需要一些帮助,以调试为什么某些模型更改事件不会像我期望的那样发射。
如果我从JSON创建一个集合 大批 从服务器中,然后以设定的间隔为fetch(),如果集合中的单个模型已更改,我不会收到通知。骨干文档表明应生成此类通知。我似乎得到的只是每个获取上的刷新通知,这无用。 OTOH,如果我从JSON创建模型 目的 从服务器中,然后以设定的间隔为fetch(),当属性更改时,我确实会收到更改通知。有任何想法吗?
细节
我的Web服务在/雇员/{用户名}/任务返回任务对象的JSON数组,每个任务对象都嵌套了子任务对象的JSON数组。例如,
[{
"id":45002,
"name":"Open Dining Room",
"subtasks":[
{"id":1,"status":"YELLOW","name":"Clean all tables"},
{"id":2,"status":"RED","name":"Clean main floor"},
{"id":3,"status":"RED","name":"Stock condiments"},
{"id":4,"status":"YELLOW","name":"Check / replenish trays"}
]
},{
"id":47003,
"name":"Open Registers",
"subtasks":[
{"id":1,"status":"YELLOW","name":"Turn on all terminals"},
{"id":2,"status":"YELLOW","name":"Balance out cash trays"},
{"id":3,"status":"YELLOW","name":"Check in promo codes"},
{"id":4,"status":"YELLOW","name":"Check register promo placards"}
]
}]
另一个Web服务使我可以在特定任务中更改特定子任务的状态,并且看起来像这样:/tasks/45002/subtasks/1/status/status/red [旁边 - 我打算将其更改为基于HTTP的服务,但是当前的实现更容易进行调试
我的JS应用程序中有以下课程:
子任务模型和子任务集合
var Subtask = Backbone.Model.extend({});
var SubtaskCollection = Backbone.Collection.extend({
model: Subtask
});
带有子任务集合的嵌套实例的任务模型
var Task = Backbone.Model.extend({
initialize: function() {
// each Task has a reference to a collection of Subtasks
this.subtasks = new SubtaskCollection(this.get("subtasks"));
// status of each Task is based on the status of its Subtasks
this.update_status();
},
...
});
var TaskCollection = Backbone.Collection.extend({
model: Task
});
任务视图以渲染项目并聆听对模型的更改事件
var TaskView = Backbone.View.extend({
tagName: "li",
template: $("#TaskTemplate").template(),
initialize: function() {
_.bindAll(this, "on_change", "render");
this.model.bind("change", this.on_change);
},
...
on_change: function(e) {
alert("task model changed!");
}
});
当应用启动时,我实例化任务汇总(使用上面列出的第一个Web服务中的数据),将侦听器绑定到“将事件更改”的侦听器绑定到TaskCollection,并设置一个重复的Settimeout以fetch(fetch()fetch()TaskCollection实例。
...
TASKS = new TaskCollection();
TASKS.url = ".../employees/" + username + "/tasks"
TASKS.fetch({
success: function() {
APP.renderViews();
}
});
TASKS.bind("change", function() {
alert("collection changed!");
APP.renderViews();
});
// Poll every 5 seconds to keep the models up-to-date.
setInterval(function() {
TASKS.fetch();
}, 5000);
...
一切都按预期的是第一次渲染。但是在这一点上,如果我使用第二个Web服务更改子任务的状态,我希望(或两者都)(或两者都)(或两者都)将收集更改事件或模型更改事件被解雇,但这不会发生。
有趣的是,如果我添加了一个,我确实会开火 额外的 嵌套级别,Web服务返回单个模型,例如:
"employee":"pkaushik", "tasks":[{"id":45002,"subtasks":[{"id":1.....
但这似乎是克鲁吉...恐怕我还没有对我的应用程序进行正确的架构。如果有帮助,我将包括更多代码,但是这个问题已经相当详细。
想法?
解决方案
您正在聆听任务上的事件,而不是您的子任务。如果您希望自己的任务随身携带子任务的事件,则应该在任务中执行类似的操作。
var self = this;
this.subtasks.bind("refresh", function(){ self.trigger("refresh:subtask")});
this.subtasks.each(function(st){
st.bind("change", function(){ self.trigger("change:subtask:" + st.id, st) });
});
您可能还需要在刷新事件后刷新绑定。这样,当更改事件发生在子任务模型上时,任务模型也将触发变更模型。
骨干只能在获取后发送刷新事件,您不会被告知特定模型中的更改。查看集合的获取功能:
options.success = function(resp) {
collection[options.add ? 'add' : 'refresh'](collection.parse(resp), options);
if (success) success(collection, resp);
};
默认情况下将调用刷新。这是刷新功能:
refresh : function(models, options) {
models || (models = []);
options || (options = {});
this.each(this._removeReference);
this._reset();
this.add(models, {silent: true});
if (!options.silent) this.trigger('refresh', this, options);
return this;
}
它将将所有模型静静地添加到集合中(无事件),然后触发刷新事件,但不会识别更改的元素。