2

我在尝试在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",
    "hea‌​rt": "No",
    "alzheimers": "No",
    "parkinsons": "No",
    "mentalHealth": "No",
    "breastOvarianCa‌​ncer": "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
    }
});
4

1 回答 1

1

看起来问题在于它的构造方式......我认为之前没有render调用过success_handler

如果您查看renderPrereq方法,则 2 模型更改将在成功时调用此方法。

但是这些fetch方法是异步的。所以你永远不知道哪个处理程序会首先被调用。

并且当change模型被触发时。这会调用render方法内部的renderPrereq方法。

于 2013-06-26T18:24:08.077 回答