我在尝试在backbone.js 中使用具有相同视图的两个模型时遇到了麻烦。在触发器被触发以开始渲染功能之前,视图正在以某种方式被渲染。
以下是模型:
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler});
},
success_handler: function(){
this.trigger("change");
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function( attributes, options ) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function(){
this.fetch({success: this.success_handler, error:this.error_handler});
},
success_handler: function(){
this.exists = true;
this.trigger("change");
},
error_handler: function(){
this.exists = false;
this.trigger("change");
}
});
以下是视图中的相关代码:
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{name:"preferences_template", file_path:"preferences_form.html"}],
initialize: function(options){
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
this.models.family = new APP.Models.FamilyPreferences({}, {url: family_url});
this.models.family.on('change', function(){ctx.renderPrereq("family");});
this.models.family.populate();
this.models.preferences = new APP.Models.Preferences({}, {url:preferences_url});
this.models.preferences.on('change', function() {ctx.renderPrereq("preferences");});
this.models.preferences.populate();
},
renderPrereq: function(newmodel){
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded)>-1) ? true : false;
if (!(inside)){this.modelsCurrentlyLoaded.push(newmodel);}
var total = Object.keys(this.models).length;
if(this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered){
this.alreadyRendered = true;
this.render();
}
},
render: function(){
var family_data = {
id: this.models.family.attributes.id,
familyGroup: this.models.family.attributes.groupNum,
familyId: this.models.family.attributes.familyId,
probandDob: this.models.family.attributes.childDob,
}
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.exists
}
this.$el.html(this.compiledTemplates.preferences_template(family_data));
//bunch of javascript making the page work
}
});
该模板正在通过其他地方的另一个 js 函数加载,据我所知,该函数工作正常。不知何故,渲染函数在成功处理程序之前被调用。我不知道怎么做。它唯一的副作用是 Preferences 模型没有获得 exists 属性,因此未定义,这会导致各种问题。此外, options.family_id 设置正确。任何帮助,将不胜感激。先感谢您。
编辑:它似乎也将 renderPrereq 多达六次,我也无法弄清楚。
JSON - 家庭模型
{
"id": 1,
"familyId": "family01",
"collectionDate": "2013-01-01",
"childDob": "2001-05-06",
"groupNum": "Two",
"probands": [],
"mother": null,
"father": null,
"siblings": []
}
JSON - 首选项模型的第一部分
[{
"main": "illness-only",
"obesity": "No",
"bloodPressure": "No",
"diabetes": "No",
"heart": "No",
"alzheimers": "No",
"parkinsons": "No",
"mentalHealth": "No",
"breastOvarianCancer": "No",
"prostateTesticularCancer": "No",
"otherCancer": "No",
"childSickleCell": "No",
"childCysticFibrosis": "No",
"childMuscularDystrophy": "No",
"childAutism": "No"
},
{
"main":"more-questions",
"obesity":"No",
"bloodPressure":"Yes",
"diabetes":"No",
"heart":"Unsure",
"alzheimers":"No",
"parkinsons":"Yes",
"mentalHealth":"No",
"breastOvarianCancer":"No",
"prostateTesticularCancer":"No",
"otherCancer":"No",
"childSickleCell":"No",
"childCysticFibrosis":"No",
"childMuscularDystrophy":"No",
"childAutism":"No"}]
标头
Accept: application / json, text / javascript, /; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache Connection:keep-alive
Cookie:csrftoken=bDIpdvAPBdWF6dZe9BkpsFSF4wiGl2qX
Host:localhost:8080 Pragma:no-cache Referer:localhost:8080/CSER / index.html
User - Agent: Mozilla / 5.0(Macintosh; Intel Mac OS X 10_8_3) AppleWebKit /
537.36(KHTML, like Gecko) Chrome / 27.0.1453.110 Safari / 537.36 X - Requested - With: XMLHttpRequest
试试这个代码..
APP.Models.FamilyPreferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch();
},
// This is not required
// It will automatically render it as we are listening to the sync event
success_handler: function () {
// Not required
// sync event will take care of it
}
});
APP.Models.Preferences = Backbone.Model.extend({
initialize: function (attributes, options) {
_.bindAll(this, 'success_handler', 'error_handler', 'populate');
this.url = options.url;
},
populate: function () {
this.fetch({
success: this.success_handler,
error: this.error_handler
});
},
success_handler: function () {
this.exists = true;
// Not required
// sync event will take care of it
},
error_handler: function () {
// Do something else
}
});
APP.Views.PreferencesFormView = Backbone.View.extend({
templates: [{
name: "preferences_template",
file_path: "preferences_form.html"
}],
initialize: function (options) {
_.bindAll(this, 'render', 'renderPrereq');
var family_url = "services/family/" + options.family_id;
var preferences_url = "services/preferences/familyID/" + options.family_id;
var ctx = this;
this.alreadyRendered = false;
this.modelsCurrentlyLoaded = [];
this.models = {};
// Family Model
this.models.family = new APP.Models.FamilyPreferences({}, {
url: family_url
});
this.listenTo( this.models.family, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.family, 'sync', function () {
ctx.renderPrereq("family");
});
this.models.family.populate();
// Family Preference Model
this.models.preferences = new APP.Models.Preferences({}, {
url: preferences_url
});
this.listenTo( this.models.preferences, 'change', function () {
ctx.renderPrereq("family");
});
// This will take care of rendering it on Sync with server
// No need to triggereing the event explicitly..
this.listenTo( this.models.preferences, 'sync', function () {
ctx.renderPrereq("preferences");
});
this.models.preferences.populate();
},
renderPrereq: function (newmodel) {
var inside = ($.inArray(newmodel, this.modelsCurrentlyLoaded) > -1) ? true : false;
if (!(inside)) {
this.modelsCurrentlyLoaded.push(newmodel);
}
var total = Object.keys(this.models).length;
if (this.modelsCurrentlyLoaded.length == total && !this.alreadyRendered) {
this.alreadyRendered = true;
this.render();
}
},
render: function () {
var family_data = this.models.family.toJSON());
var preferences_data = {
mother: this.models.preferences.attributes[0],
father: this.models.preferences.attributes[1],
exists: this.models.preferences.get('exists') ? this.models.preferences.get('exists') : false
}
this.$el.html(this.compiledTemplates.preferences_template(family_data);
//bunch of javascript making the page work
}
});