Backbone.js 在主干网中进行视图混合的正确方法

Backbone.js 在主干网中进行视图混合的正确方法,backbone.js,Backbone.js,我一直在扩展基本主干视图,每个部分都有一个基本视图,这样我就可以在多个级别上进行扩展。我的问题是,进行视图混合最有效的方法是什么:可以混合到任何视图中的可重用视图部分。例如: var BaseProfile = Backbone.View.extend({ ...}); var UserProfile = BaseProfile.extend({ ...}); var VideoSupport = Backbone.View.extend({ ...}); 将VideoSupport视图(一个

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

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

VideoSupport
视图(一个事件对象和一些方法)与
UserProfile
视图混合在一起的最佳方法是什么?

underline.js库提供了一种满足您需要的
扩展
方法。您可以在任何对象上定义功能,然后将所有方法和属性从该对象复制并粘贴到另一个对象

主干网在视图、模型和路由器上的
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"

您可以使用这个要点

我需要更接近ruby如何处理模块的覆盖和调用混合方法(ala super)的能力。如果mixin方法存在于类中,那么简单的扩展方法将对其进行重击。由于我在CoffeeScript中构建了所有内容,因此我可以访问super对象,该对象允许我填充方法。它还将自动合并事件对象,以便您可以在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) 

    @
用法 我可能会建议使用它,它提供了一种非常简洁的方式来指定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"
    }
});

另一个选项是提供AOP样式的混合功能(您可以在扩展对象方法的调用之前、之后或前后注入自定义行为)。

感谢Derek,我认为默认值更合适,这样混合视图属性和方法就不会被覆盖。不过,正确的做法是,如果mixin将扩展它所混入的“类”的事件和init函数。另外,在您的示例中,您是否会扩展MyView.prototype而不是MyView函数类?这是一种方法,但需要注意的是,您通常希望扩展prototype。@maxl0rd-完全正确。我改变了它,以反映最常见的情况。在所有人中,德里克都知道这一点,但我认为我应该对最常见的情况给出答案是的,那应该在原型上。感谢您对有关使用u.defaults而不是u.extend.的评论进行编辑+1。。需要注意的是,人们可能不理解Derick在做什么,因为默认值是一个不太广为人知的功能。虽然此链接可能会回答这个问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能会无效。@S.L.Barth-虽然我同意内联代码更有用-这是一个具有社区编辑功能的系统,因此请随意复制此处的代码以改进anser。在IE8中使用此方法时,我遇到了一些麻烦。Firefox、Chrome、Safari和IE9+目前正在运行。知道为什么它在IE8中不起作用吗?IE8中的控制台根本不显示任何消息…+1表示鸡尾酒。与接受的答案不同,此解决方案合并了mixin和View事件散列(以及任何其他对象,如木偶的ui或modeleevents散列)。
var Mixin = {
  initialize: function() {
    console.log("I'll be called as well as the class's constructor!");
  }
};

var View = Backbone.View.extend({
  mixins: [ MyMixin ]
});
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"
    }
});