2

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

  1. 不牺牲可读性
  2. 不涉及很多样板
  3. 不会产生任何意想不到的后果

这是我的一般视图结构:

(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);
        }
    });
}());

我最喜欢这个;这很有效,可读性很强,并且可以像宣传的那样工作,但同样,对于每个视图来说,这是一个额外的步骤。我还缺少其他解决方案吗?

4

2 回答 2

1

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

this.collection.each(addStuffToMyDom, this);

现在this将是你的视图里面addStuffToMyDom

我想当你使用 Backbone 事件哈希来连接事件时,它做了类似的事情。你确定this不是里面的景色doSomeThingTrivial吗?

如果您查看 Backbone delegateEvents,它会执行以下操作:

method = _.bind(method, this);

this你的观点在哪里。

于 2013-02-06T19:52:09.927 回答
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);

        }
    });
 }());
于 2013-05-12T18:43:10.890 回答