【问题标题】:Proper way of doing view mixins in Backbone在 Backbone 中进行视图混合的正确方法
【发布时间】:2011-10-21 18:32:28
【问题描述】:

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

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

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

【问题讨论】:

    标签: backbone.js


    【解决方案1】:

    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"
    

    【讨论】:

    • 谢谢 Derek,我想 _.defaults 会更合适,这样 mixin 视图的属性和方法就不会被覆盖。不过,适当的是,如果 mixin 会扩展它正在混入的“类”的事件和 init 函数。同样在您的示例中,您是否不会扩展 MyView.prototype 而不是 MyView 函数类?
    • 这是要走的路,但是需要注意的是,您通常希望扩展原型。
    • @maxl0rd - 没错。我已经改变了它以反映最常见的情况。德里克,在所有人中,都知道这一点,但我想我会反映最常见情况的答案。
    • 哎呀。 :) 是的-应该在原型上。感谢您的编辑
    • +1 对关于使用 _.defaults 而不是 _.extend 的评论 .. 需要注意的是人们可能不明白 Derick 在做什么,因为 defaults 是一个鲜为人知的功能。
    【解决方案2】:

    我可能会推荐使用Backbone.Cocktail,它提供了一种非常简洁的方式来指定混合(尊重继承):

    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中详细说明了。

    【讨论】:

    • 鸡尾酒+1。此解决方案与公认的答案不同,它合并了 mixin 和 View 事件哈希(以及任何其他对象,如 Marionette 的 ui 或 modelEvents 哈希)。
    【解决方案3】:

    你可以使用这个要点https://gist.github.com/3652964

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
    • @S.L.Barth - 虽然我同意将代码内联更有帮助 - 这是一个具有社区编辑能力的系统,因此请随意复制代码以改进分析器。
    【解决方案4】:

    你可以使用Backbone.Mix library,它使用了嵌入到原型链中的mixins

    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】:

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

      _.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
      

      【讨论】:

      • 我在 IE8 中使用这种方法遇到了一些麻烦。到目前为止,Firefox、Chrome、Safari 和 IE9+ 都在工作。知道为什么它在 IE8 中不起作用吗? IE8 中的控制台根本不显示任何消息...
      【解决方案6】:

      另一个选项是Backbone.Advice,它提供了强大的 AOP 风格的 mixins(你可以注入自定义行为 beforeafteraround扩展对象方法的调用)。

      【讨论】:

        猜你喜欢
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多