Backbone,在model.save之后调用view.render时未设置的一个字段

时间:2012-07-13 12:39:56

标签: backbone.js backbone-views

我有以下问题。在用户事件上(单击.twitterDefault),我使用

调用save事件
twitter : {
                    handle : handle,
                    ignore : false
}

然后调用成功函数,我在模型上设置字段(klout,twitter和tester)。设置所有字段(记录语句都打印出适当的对象。

但是,然后我调用view.render(),这里不再设置twitter。我不知道为什么,保存后没有同步发生,所以twitter不会被覆盖(另外我确保在调用成功方法之前,twitter也会保存在服务器上)。

任何帮助都非常感谢!

代码如下(剥离以提高可读性)

  

$(function(){

var ContactModel,
    ContactModelCollection,
    ContactView,
    ContactCollectionView,
    contacts,
    contactCollectionView;

//base model
ContactModel = Backbone.Model.extend({
    defaults : {
    },
    initialize : function() {
    }
});

ContactModelCollection = Backbone.Collection.extend({
    model : ContactModel,
    url : '/api/contacts',
    comparator : function(contact) {
        return contact.get('strength_of_relationship');
    },
    initialize : function() {
    }
});

ContactView = Backbone.View.extend({
    tagName : 'li', //attempting to create a new element
    render: function() {
        var compiled_tmpl = _.template($('#contact-template').html());
        var html = compiled_tmpl(this.model.toJSON());
        console.log('model.get("twitter")=('+JSON.stringify(this.model.get('twitter)'))+')');
        console.log('model.get("klout")=('+JSON.stringify(this.model.get('klout'))+')');
        console.log('model.get("tester")=('+JSON.stringify(this.model.get('tester'))+')');
        this.$el.html(html);
        console.log('rendered view successfully)');
        return this;
    },
    initialize: function() {
        console.log('contactView initalized');
        this.model.bind('change', this.render, this);
        this.model.bind('destroy', this.remove, this);
    },
    events: {
        'click .twitterDefault' : 'assignDefaultTwitterHandle',
    },
    assignDefaultTwitterHandle : function(event) {
        var handle = $(event.currentTarget).data('twitter');
        this.assignTwitterHandle(handle);
    },
    assignTwitterHandle : function(handle) {
        console.log('model assignTwitterHandle. handle='+handle+')');
        var view = this,
            model = view.model;
        model.save({
            twitter : {
                handle : handle,
                ignore : false
            },
            id : model.get('id')
        }, {
            error : function() {
                console.log('saving twitter handle failed');
            },
            success : function(model, response) {
                console.log('response=('+JSON.stringify(response)+')');
                if(response.error) {
                    console.log('error on server ='+response.error);
                }
                if(response.twitter) {
                    console.log('twitter is set');
                    var twitter = {
                        handle : handle,
                        tweet : response.twitter,
                        age : new Date()
                    };
                    console.log('setting twitter to '+JSON.stringify(twitter));
                    model.set('twitter', twitter);
                    model.set('tester', 'tester');
                    console.log('twitter after setting it = '+JSON.stringify(model.get('twitter')));
                    console.log('view\'s model twitter after setting it = '+JSON.stringify(view.model.get('twitter')));
                }

                if(response.klout) {
                    console.log('klout is set');
                    var klout = {
                        topics : response.klout
                    }
                    console.log('setting klout to '+JSON.stringify(klout));
                    model.set('klout', klout);
                }
                if(response.twitter || response.klout) {
                    console.log('Rerendering view after setting klout/twitter');
                    view.render();
                }
            }
        });
    }
});

contacts = new ContactModelCollection;

ContactCollectionView = Backbone.View.extend({
    el : $('#suggestions-list'),
    initialize : function(){
        contacts.bind('add', this.addOne, this);
        contacts.bind('reset', this.addAll, this);
        contacts.bind('all', this.render, this);
    },
    render : function(){
        console.log('contactcollectionview render');
    },
    addOne : function(contact) {
        console.log('addOne');
        var view = new ContactView({model: contact});
        var el = view.render().el;
        console.log('el=('+el+')');
        $('#suggestions-list').append(el); 
    },
    addAll : function() {
        console.log('addAll');
        contacts.each(this.addOne);
    }
});

contactCollectionView = new ContactCollectionView;


App.contacts = contacts;
App.contactCollectionView = contactCollectionView; });

1 个答案:

答案 0 :(得分:0)

我猜问题是render函数的范围。 根据调用的位置,this采用不同的值。

要始终this指向视图范围的保修,请添加到initialize

_.bindAll(this,"render");

此外,手动调用view.render并不是一个好习惯。你应该让事件发挥作用。 Model save已经触发了一些事件。只需听取他们更新您的视图。