为多个Backbone Marionette视图添加UI增强功能的最佳实践

时间:2013-08-14 16:41:44

标签: backbone.js marionette

因此,对于在元素上执行操作的应用程序中的所有视图,我是最好的方法。

在非单页面应用程序中,您可以运行说:

$(document).ready(function() { 
    $('.autosize').autosize();
});

将autosize函数应用于每页上具有autosize类的所有元素。

现在,在Backbone Marionette应用程序中,您可以使用onDomRefresh或类似的方式在每个视图中执行此操作,但对于影响90%视图的内容,您希望以某种方式自动运行。

我不认为Application对象可以监听可能解决它的所有onDomRefresh事件。我考虑重载Marionette.MonitorDOMRefresh以添加它,但它不像是一个Backbone方法。

我考虑的其他事情是对每个木偶视图进行子类化,以添加用于加载不同UI元素组的mixins。

我认为其他人必须经历过这种情况,所以对使用了什么方法感兴趣。

3 个答案:

答案 0 :(得分:0)

只需创建一个基本View类并从中继承需要自动调整大小增强的每个视图类。

var AutosizeBaseView = Backbone.Marionette.ItemView.extend({
    onDomRefresh: function(){
        this.$('.autosize').autosize();
    }
});

然后让你的课程像这样:

var SomeView = AutosizeBaseView.extend({
});

答案 1 :(得分:0)

所以我无法找到真正解决我问题的任何解决方案,尽管在Twitter上与@julio_menedez和@marionettejs进行了一些有用的聊天。有一个非常好的主意使用Polymer,但不适合,因为我需要支持旧的IE。

所以相反,我进入猴子修补的危险世界来解决它(请记住,我可能需要用这个来解决一些皱纹,刚完成编写它并没有完全测试它 - 我会相应更新)< / p>

在Coffeescript中:(底部是javascript版本)

# Monkey patching the Marionette View.. sorry!

# this is the only Marionette view which doesn't have it's own constructor
Marionette.ItemView = Marionette.ItemView.extend
  constructor: ->
    Marionette.View.prototype.constructor.apply @, Array.prototype.slice.call(arguments, 0)

original_view_constructor = Marionette.View.prototype.constructor
Marionette.View.EventAggregator = event_aggregator = _.extend {}, Backbone.Events

# all the other constructors call this so we can hijack it
Marionette.View.prototype.constructor = ->
  event_aggregator.listenTo @, 'all', =>
    args_array = Array.prototype.slice.call arguments, 0
    event_aggregator.trigger.apply event_aggregator, [ 'view:' + args_array[0], @ ].concat(args_array.slice(1))
    event_aggregator.stopListening @ if args_array[0] == 'close'
  original_view_constructor.apply @, Array.prototype.slice.call(arguments, 0)

然后使用我只是在我的应用程序对象中设置一个监听器来捕获我需要的视图事件。例如:

@listenTo Marionette.View.EventAggregator, 'view:dom:refresh', (view) ->
  view.$('div').css('backgroundColor', 'red');

所以我认为这些是这种技术的优点和缺点:

优点:

  • 可以在不注入所有视图类或子类化所有视图类的情况下监听所有视图事件
  • 简单易用
  • 对象无需选择使用它

缺点

  • 使用猴子修补,对Marionette API更改很危险
  • 使用Marionette命名空间非常容易受到未来Marionette名称空间冲突的影响
  • 处理视图外的视图
  • 有一个事件聚合器对象在Backbone / Marionette(afaiw)的其他地方看不到,所以打破了一个模式(更新 - 与Backbone.history类似的东西)

无论如何,我欢迎提供反馈,替代方案,批评:-)并希望这可以帮助处于同样情况的其他人

使用Javascript:

(function() {
  var event_aggregator, original_view_constructor;

  Marionette.ItemView = Marionette.ItemView.extend({
    constructor: function() {
      return Marionette.View.prototype.constructor.apply(this, Array.prototype.slice.call(arguments, 0));
    }
  });

  original_view_constructor = Marionette.View.prototype.constructor;

  Marionette.View.EventAggregator = event_aggregator = _.extend({}, Backbone.Events);

  Marionette.View.prototype.constructor = function() {
    var _this = this;
    event_aggregator.listenTo(this, 'all', function() {
      var args_array;
      args_array = Array.prototype.slice.call(arguments, 0);
      event_aggregator.trigger.apply(event_aggregator, ['view:' + args_array[0], _this].concat(args_array.slice(1)));
      if (args_array[0] === 'close') {
        return event_aggregator.stopListening(_this);
      }
    });
    return original_view_constructor.apply(this, Array.prototype.slice.call(arguments, 0));
  };

}).call(this);

答案 2 :(得分:0)

在CoffeeScript中我认为你也可以这样做:

extend = (obj, mixin) ->
  obj[name] = method for name, method of mixin        
  obj

include = (klass, mixin) ->
  extend klass.prototype, mixin

include Marionette.View,
  onDomRefresh: () -> @$('.autosize').autosize()

哪个应涵盖所有视图类型。没有专门测试过这个,但只是做了一些非常类似于为Marionette的布局视图添加功能的东西。在http://arcturo.github.io/library/coffeescript/03_classes.html扩展/包含模式。当然,这也应该直接在JS中实现。

更新:

实际上,由于我们可以使用下划线,因此我们无需手动定义includeextend方法。我们可以说:

_.extend Marionette.View.prototype,
  onDomRefresh: () -> @$('.autosize').autosize()