4

I am confused about binding and the purpose of _bind.All in backbone.js. Below is a working code that creates a Modal view #modal and renders out comments fetched from the backend.

Firstly, in the code below, I have in the initialize function _.bindAll(this, 'render', 'renderComments');. Whether or not I do _.bindAll(), I have no problems calling this.render() and this.renderComments() inside initialize(). Are there any examples of when _.bindAll() will help us and when it will not?

ModalView = Backbone.View.extend({
    el: $('#modal'),

    template: _.template( $('#tpl_modal').html() ),

    initialize: function() {
        _.bindAll(this, 'render', 'renderComments');
        this.render();
        this.renderComments();
    },

    render: function() {
        $(this.el).fadeIn('fast').append( this.template( this.model.toJSON( this.model ) ) );
    },

    renderComments: function() {
        this.commentList = new CommentCollection();
        var self = this;
        this.commentList.fetch({
            data: { post_id: this.model.id},
            processData: true,
            success: function() {
                self.commentListView = new CommentListView({ collection: self.commentList });
            }
        });
    }
});

And

CommentListView = Backbone.View.extend({
    el: '.modal_comments',

    initialize: function() {
        this.render();
    },

    render: function() {
        var self = this;
        this.collection.each( function(comment, index) {
            $(self.el).append( new CommentListItemView({ model: comment }).render().el );
        });
        return this;
    }
});

Secondly, I am confused about prepending this. to something. For example in renderComments, why cant I use:

var commentList = new CommentCollection();
var self = this;
commentList.fetch({.... });

For the line this.commentList = new CommentCollection();, other than instantiating the class CommentCollection(), does it make commentList a child of ModalView?

Additionally, is it necessary to have var self = this; and use self.commentListView later in the callback function? Can binding be used so I can access this.commentListView, or is using var self = this the conventional way of doing things?

Finally, should self.commentListView = new CommentListView({ collection: self.commentList }); in the success function of renderComments be moved to CommentListView's initialize method instead and be binded to this.collection.on('reset'); to prevent nesting too many functions? This will result in:

ModalView = Backbone.View.extend({
    el: $('#modal'),

    template: _.template( $('#tpl_modal').html() ),

    initialize: function() {
        _.bindAll(this, 'render', 'renderComments');
        this.render();
        this.renderComments();
    },

    render: function() {
        $(this.el).fadeIn('fast').append( this.template( this.model.toJSON( this.model ) ) );
    },

    renderComments: function() {
        this.commentList = new CommentCollection();
        this.commentListView = new CommentListView({ collection: this.commentList });
        this.commentList.fetch({
            data: { post_id: this.model.id},
            processData: true
        });
    }
});

CommentListView = Backbone.View.extend({
    el: '.modal_comments',

    initialize: function() {
        this.collection.on('reset', this.render, this);
    },

    render: function() {
        var self = this;
        this.collection.each( function(comment, index) {
            $(self.el).append( new CommentListItemView({ model: comment }).render().el );
        });
        return this;
    }
});
4

1 回答 1

8

唷——长问题;)

1)_.bindAll当我第一次使用主干时,我曾经在我的初始化方法中做过,但后来我停止了。通常不需要它,除非你绑定到事件,然后它真的很有帮助。例如,如果您有:

events:
{
    'click': clickHandler
},
clickHandler: function(){
    //do cool stuff
}

那么这样做会很有帮助,_.bindAll(this, 'clickHandler')否则您的this指针将不会是视图

2)如果我理解您的问题:commentList成为您的实例的属性ModalView

3) usingvar self = this;比较常见,但在很多情况下可以避免因为 Underscore.js 中的重载(这是backbone.js 的依赖项)。例如,大多数集合函数(mapeach等)都将上下文作为最后一个参数。所以而不是

var self = this;
_.map([1,2], function(item){
    self.sum = self.sum + item; 
});

你可以做:

_.map([1,2], function(item){
    this.sum = this.sum + item; 
}, this);

如果你的情况你可以success

success: _.bind(function() {
             this.commentListView = new CommentListView({ collection: this.commentList });
         }, this);

如果您想了解更多关于这个指针有点令人困惑的主题的信息,建议您阅读以下优秀教程: http ://bonsaiden.github.com/JavaScript-Garden/#function.this

4) 是的——我会将渲染移至reset. 这样,如果其他原因导致集合重置,视图将拾取它。

希望我回答了你所有的问题。

于 2012-07-09T21:29:46.710 回答