Backbone Views中的私有事件处理程序

时间:2013-02-06 19:23:37

标签: javascript backbone.js backbone-views

我正在试图找到一种方法来保持我的私有函数和辅助方法真正私密。每个对象应该只公开允许外部调用的内容(激进,我知道!)。我很难用Backbone视图执行此操作:

  1. 不牺牲可读性
  2. 不涉及大量样板
  3. 没有任何意外后果
  4. 这是我的一般视图结构:

    (function(){
        //Private function no other view needs to care about
        var addStuffToMyDom = function(model){
            var newView = new Subview({model: model});
    
            //Problem: this doesn't refer to the 'view' here
            this.$el.append(newView.render().$el);
        }
    
        //Another trivial function which should really be private
        var doSomeThingTrivial = function(){
            this.$el.addClass("meh");
        }
    
        return BaseView.extend({
            events: {
                "click": doSomeThingTrivial
            },
    
            render: function(){
                var me = this;
                this.collection.each(addStuffToMyDom);
                return this;
            }
        });
     }());
    

    正如您所看到的,私有函数无法引用'this'来追加自己。

    解决方案1:

    (function(){
        var me;
    
        ...
    
        return BaseView.extend({
            initialize: function(){
                me = this;
            }
        });
    }());
    

    这有很多微妙的副作用+每次都必须这样做会很烦人。

    解决方案2:

    (function(){
        var me;
    
        ...
    
        return BaseView.extend({
            events{
                "click" : function(){
                    doSomeThingTrivial.call(this);
                }
            }
        });
    }());
    

    这很有用,但是它有很多代码混乱的样板。

    解决方案3:

    (function(){
        return BaseView.extend({
                events: {..}
            initialize: function(){
                _.bindAll(this, this.events);
            }
        });
    }());
    

    我最喜欢这个;这是有效的,并且具有相当的可读性,并且可以像宣传的那样工作,但同样,这也是为每个视图做的额外步骤。我还缺少其他任何解决方案吗?

2 个答案:

答案 0 :(得分:1)

您可以将要使用的上下文传递给each方法:

this.collection.each(addStuffToMyDom, this);

现在this将是您addStuffToMyDom内的视图。

我认为当你使用Backbone事件哈希来连接事件时,它做了类似的事情。您确定this不是doSomeThingTrivial内的视图吗?

如果你看一下Backbone delegateEvents,就会这样做:

method = _.bind(method, this);

this是您的观点。

答案 1 :(得分:1)

发现初始化程序中的_.bindAll(this)修复了私有函数中的范围问题。自从我问这个问题以来,我对这种设计模式越来越不相信了,但确实解决了这个问题:)

(function(){
    //Private function no other view needs to care about
    var addStuffToMyDom = function(model){
        var newView = new Subview({model: model});

        //Problem: this doesn't refer to the 'view' here
        this.$el.append(newView.render().$el);
    }

    //Another trivial function which should really be private
    var doSomeThingTrivial = function(){
        this.$el.addClass("meh");
    }

    return BaseView.extend({
        events: {
            "click": doSomeThingTrivial
        },

        initialize: function(){
            _.bindAll(this);

        }
    });
 }());