在Backbone中进行视图混合的正确方法

时间:2011-10-21 18:32:28

标签: backbone.js

我一直在扩展基础骨干视图,并且每个部分都有一个基本视图,以便我可以在多个级别上进行扩展。我的问题是,查看混合的最有效方法是什么:可以混合到任何视图中的可重用视图部分。例如:

var BaseProfile = Backbone.View.extend({ ...});
var UserProfile = BaseProfile.extend({ ...});
var VideoSupport = Backbone.View.extend({ ...});

VideoSupport视图(事件对象和几种方法)与UserProfile视图混合的最佳方法是什么?

6 个答案:

答案 0 :(得分:111)

underscore.js库提供了一个extend方法,可以执行您想要的操作。您可以在任何对象上定义功能,然后完全复制&将该对象的所有方法和属性粘贴到另一个。

视图,模型和路由器上的Backbone的extend方法是下划线extend的包装。

 var MyMixin = {
  foo: "bar",
  sayFoo: function(){alert(this.foo);}
}

var MyView = Backbone.View.extend({
 // ...
});

_.extend(MyView.prototype, MyMixin);

myView = new MyView();
myView.sayFoo(); //=> "bar"

答案 1 :(得分:19)

我可能会建议使用Backbone.Cocktail,它提供了一种非常简洁的方法来指定mixins(尊重继承):

var Mixin = {
  initialize: function() {
    console.log("I'll be called as well as the class's constructor!");
  }
};

var View = Backbone.View.extend({
  mixins: [ MyMixin ]
});

我已在此blog post详细说明。

答案 2 :(得分:3)

您可以使用此要点https://gist.github.com/3652964

答案 3 :(得分:3)

您可以使用Backbone.Mix library使用嵌入原型链的mixin

var Editable = {
    edit: function(){
        console.log('edit');
    }
};

var Article = Backbone.Model.mix(Editable).extend({
    initialize: function(){
        Backbone.Model.prototype.initialize.call(this);
        this.edit(); // logs "edit"
    }
});

答案 4 :(得分:2)

我需要能够覆盖和调用混合方法(ala super),更接近ruby处理模块的方式。如果它存在于类中,那么简单的扩展方法会破坏mixin方法。由于我在CoffeeScript中构建它,我可以访问 super 对象,它允许我使用shim方法。它还将自动合并事件对象,以便您可以在mixin中定义事件处理程序。

_.extend Backbone,
  mixin: (klass, mixin, merge) ->
    debugger unless mixin
    mixin = mixin.prototype || mixin
    merge ||= ["events"]

    sup = _.extend({},klass.__super__)

    for name,func of mixin      
      if base = sup[name] && _.isFunction(base)
        sup[name] = ->
          func.apply this, arguments
          base.apply this, arguments
      else
        sup[name] = func

    hp = {}.hasOwnProperty
    prototype = klass.prototype
    for name,func of mixin
      continue unless hp.call(mixin,name)
      continue if _(merge).contains name
      prototype[name] = func unless prototype[name]

    klass.__super__ = sup

    _(merge).each (name) ->
      if mixin[name]
        prototype[name] = _.extend({},mixin.events,prototype.events) 

    @

用法

class SimpleView extends Backbone.View
  events:
    "click .show" : "show"

  calculate: ->
    super + 5

  show: ->
    console.log @calculate()

class CalculatableViewMixin
  events:
    "click .calculate" : "show"

  calculate: ->
    15

Backbone.mixin SimpleView, CalculatableViewMixin

答案 5 :(得分:1)

另一种选择是Backbone.Advice提供AOP风格的mixins的强大功能(你可以在之前注入自定义行为,在之后注入 strong>调用扩展对象方法)。