Правильный способ просмотра смесей в Backbone

Я постоянно расширяю базовые представления и имею базовый вид для каждого раздела, чтобы я мог распространяться на нескольких уровнях. Мой вопрос в том, что самый эффективный способ просмотра mixins: многоразовые частичные представления, которые можно смешать с любым представлением. Например:

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

Каков наилучший способ микширования VideoSupport (объект события и несколько методов) с представлением UserProfile?

Ответ 1

Библиотека underscore.js предоставляет метод extend, который делает то, что вы хотите. Вы можете определить функциональность на любом объекте, а затем достаточно буквально скопировать и вставить все методы и атрибуты из этого объекта в другой.

Магистральные методы 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"

Ответ 2

Я бы рекомендовал использовать Backbone.Cocktail, который обеспечивает очень сжатый способ указания mixins (что касается наследования):

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

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

Я подробно описал это сообщение .

Ответ 4

Вы можете использовать Backbone.Mix library, в которой использовались миксины, встроенные в цепочку прототипов

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

Ответ 5

Мне нужна была возможность переопределить и вызвать смешанные методы (ala super) ближе к тому, как рубины обрабатывают модули. И простой метод расширения будет clobber метод mixin, если он существовал в классе. Поскольку я создаю все это в CoffeeScript, у меня есть доступ к объекту super, который позволяет мне использовать методы shim. Он также автоматически объединяет объект events, чтобы вы могли определить обработчики событий в 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

Ответ 6

Другим вариантом является Backbone.Advice, который обеспечивает мощь микширования в стиле AOP (вы можете добавить пользовательское поведение до, после или вокруг вызовов расширенных методов объекта).