1

So I was what the best way for all views in an application to have actions performed on an element.

In a non single page application you would run say:

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

to apply autosize function to all elements with the autosize class on every page.

Now in a Backbone Marionette app to do this you could perform that in each view with onDomRefresh or similar but for things that affect 90% of views you'd want this to run automatically somehow.

I don't think there's a way that an Application object can listen to all onDomRefresh events which would potentially solve it. I've consider overloading Marionette.MonitorDOMRefreshto add this in but it doesn't feel like a Backbone approach.

Other things I considered were sub-classing each of the marionette views to add mixins for loading different groups of UI elements.

I figured other people must have experienced this scenario so was interested what approaches have been used.

4

3 回答 3

0

只需创建一个基础视图类并从它继承每个需要自动调整大小的视图类。

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

然后让你的课程像这样:

var SomeView = AutosizeBaseView.extend({
});
于 2013-08-15T15:41:50.653 回答
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 中也应该是可行的。

更新:

实际上,由于我们可以使用 Underscore,我们不需要手动定义includeandextend方法。我们只能说:

_.extend Marionette.View.prototype,
  onDomRefresh: () -> @$('.autosize').autosize()
于 2013-12-14T16:11:44.273 回答
0

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

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

在 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);
于 2013-08-19T12:41:00.817 回答